1 /*
2  * server.c: Things dealing with server connections, etc.
3  *
4  * Written By Michael Sandrof
5  *
6  * Copyright (c) 1990 Michael Sandrof.
7  * Copyright (c) 1991, 1992 Troy Rollo.
8  * Copyright (c) 1992-2000 Matthew R. Green.
9  * All rights reserved.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions and the following disclaimer.
16  * 2. Redistributions in binary form must reproduce the above copyright
17  *    notice, this list of conditions and the following disclaimer in the
18  *    documentation and/or other materials provided with the distribution.
19  * 3. The name of the author may not be used to endorse or promote products
20  *    derived from this software without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
23  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25  * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
29  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32  * SUCH DAMAGE.
33  */
34 
35 #include "irc.h"
36 #include "dma.h"
37 IRCII_RCSID("@(#)$Id: server.c,v 1.140 2000/08/05 12:19:09 mrg Exp $");
38 
39 #ifdef ESIX
40 # include <lan/net_types.h>
41 #endif /* ESIX */
42 
43 #ifdef HAVE_SYS_UN_H
44 # include <sys/un.h>
45 
46 int	connect_to_unix _((int, u_char *));
47 #endif /* HAVE_SYS_UN_H */
48 
49 #include "server.h"
50 #include "screen.h"
51 #include "ircaux.h"
52 #include "whois.h"
53 #include "lastlog.h"
54 #include "exec.h"
55 #include "window.h"
56 #include "output.h"
57 #include "parse.h"
58 #include "list.h"
59 #include "newio.h"
60 #include "vars.h"
61 #ifdef SUPPORT_ICB
62 # include "icb.h"
63 #endif
64 
65 #include "ircterm.h"
66 
67 #include "channels.h"
68 #include "ninja.h"
69 #include "socks.h"
70 #include "hosts.h"
71 
72 /* a couple ninja functions.. */
73 extern	void	addserver _((u_char *, u_char *, u_char *));
74 extern	void	removeserver _((u_char *, u_char *, u_char *));
75 
76 static	void	add_to_server_buffer _((int, u_char *));
77 static	void	login_to_server _((int));
78 static	int	connect_to_server_direct _((u_char *, int, u_char *));
79 static	int	connect_to_server_process _((u_char *, int, u_char *));
80 static	void	irc2_login_to_server _((int));
81 static	int	is_ready_for_login _((int));
82 
83 /*
84  * Don't want to start ircio by default...
85  */
86 	int	using_server_process = 0;
87 
88 /* server_list: the list of servers that the user can connect to,etc */
89 	Server	*server_list = (Server *) 0;
90 
91 /* number_of_servers: in the server list */
92 	int	number_of_servers = 0;
93 
94 #ifdef SUPPORT_ICB
95 /* do the next connect as an ICB/IRC connection */
96 	int	connect_next_as_icb = 0;
97 	int	connect_next_as_irc = 0;
98 #endif
99 
100 /* server_group_list:  list of server groups */
101 	SGroup	*server_group_list = (SGroup *) 0;
102 
103 extern	WhoisQueue	*WQ_head;
104 extern	WhoisQueue	*WQ_tail;
105 
106 	int	primary_server = -1;
107 	int	from_server = -1;
108 	int	attempting_to_connect = 0;
109 	int	never_connected = 1;		/* true until first connection
110 						 * is made */
111 	int	connected_to_server = 0;	/* true when connection is
112 						 * confirmed */
113 	u_char	*connect_next_nick;
114 	u_char	*connect_next_umode;
115 	u_char	*connect_next_password;
116 #ifdef SUPPORT_ICB
117 	u_char	*connect_next_icbgroup;
118 	u_char	*connect_next_icbmode;
119 #endif
120 	int	parsing_server_index = -1;
121 
122 extern	int	dgets_errno;
123 
124 /* rate limiting for reconnecting.. */
125 extern	time_t	last_cnct_attempt;
126 
127 #define DEFAULT_SERVER_VERSION Server2_8
128 
129 /*
130  * close_server: Given an index into the server list, this closes the
131  * connection to the corresponding server.  It does no checking on the
132  * validity of the index.  It also first sends a "QUIT" to the server being
133  * closed
134  */
135 void
close_server(server_index,message)136 close_server(server_index, message)
137 	int	server_index;
138 	u_char	*message;
139 {
140 	u_char	buffer[BIG_BUFFER_SIZE];
141 	int	i,
142 		min,
143 		max;
144 
145 	if (server_index < 0 || server_index >= number_of_servers)
146 	{
147 		min = 0;
148 		max = number_of_servers;
149 	}
150 	else
151 	{
152 		min = server_index;
153 		max = server_index + 1;
154 	}
155 	for (i = min; i < max; i++)
156 	{
157 		int	old_server = from_server;
158 
159 		if (server_list[i].flags & CLOSE_PENDING)
160 			continue;
161 		if (waiting)
162 			irc_io_loop = 0;
163 		if (i == primary_server)
164 			clean_whois_queue();
165 
166 		from_server = -1;
167 		mark_not_connected(i);
168 		from_server = old_server;
169 
170 		server_list[i].operator = 0;
171 		server_list[i].connected = 0;
172 	   server_list[i].in_ping = 0;
173 		server_list[i].buffer = (u_char *) 0;
174 		server_list[i].flags = SERVER_2_6_2;
175 		if (-1 != server_list[i].write)
176 		{
177 			if (message && *message)
178 			{
179 				sprintf(CP(buffer), "QUIT :%s\n", message);
180 				send(server_list[i].write, CP(buffer), my_strlen(buffer), 0);
181 			}
182 			new_close(server_list[i].write);
183 			if (server_list[i].write == server_list[i].read)
184 				server_list[i].read = -1;
185 			server_list[i].write = -1;
186 		}
187 		if (-1 != server_list[i].read)
188 		{
189 			new_close(server_list[i].read);
190 			server_list[i].read = -1;
191 		}
192 #ifndef _Windows
193 		if (-1 != server_list[i].pid)
194 		{
195 			kill(server_list[i].pid, SIGKILL);
196 			server_list[i].pid = (pid_t) -1;
197 		}
198 #endif /* _Windows */
199 	}
200 }
201 
202 /*
203  * set_server_bits: Sets the proper bits in the fd_set structure according to
204  * which servers in the server list have currently active read descriptors.
205  */
206 
207 void
set_server_bits(rd,wd)208 set_server_bits(rd, wd)
209 	fd_set *rd, *wd;
210 {
211 	int	i;
212 
213 	for (i = 0; i < number_of_servers; i++)
214 	{
215 		if (server_list[i].read != -1)
216 			FD_SET(server_list[i].read, rd);
217 	   if (((get_string_var(SOCKS_PROXY_VAR) && !(server_list[i].flags & SRV_CONNECTED))
218 #ifdef NON_BLOCKING_CONNECTS
219 	       || !(server_list[i].flags & (SRV_CONNECTED|CLOSE_PENDING))
220 #endif /* NON_BLOCKING_CONNECTS */
221 		)
222 	       && server_list[i].write != -1)
223 	     FD_SET(server_list[i].write, wd);
224 	}
225 }
226 
227 /*
228  * do_server: check the given fd_set against the currently open servers in
229  * the server list.  If one have information available to be read, it is read
230  * and and parsed appropriately.  If an EOF is detected from an open server,
231  * one of two things occurs. 1) If the server was the primary server,
232  * get_connected() is called to maintain the connection status of the user.
233  * 2) If the server wasn't a primary server, connect_to_server() is called to
234  * try to keep that connection alive.
235  */
236 void
do_server(rd,wd)237 do_server(rd, wd)
238 	fd_set	*rd, *wd;
239 {
240 	u_char	lbuf[BIG_BUFFER_SIZE + 1];
241 	int	des,
242 		j;
243 	static	int	times = 0;
244 	int	old_timeout;
245    u_char *socks_proxy = get_string_var(SOCKS_PROXY_VAR);
246 
247 	for (j = 0; j < number_of_servers && !break_io_processing; j++)
248 	{
249 #ifdef NON_BLOCKING_CONNECTS
250 		/*
251 		 *	deraadt@theos.com suggests that every fd awaiting connection
252 		 *	should be run at this point.
253 		 */
254 		if ((des = server_list[j].write) != -1 /* && FD_ISSET(des, wd) */)
255 	     	{
256 		   if (!(server_list[j].flags & PROXY_CONNECTED))
257 		     {
258 			if (!socks_proxy)
259 			  server_list[j].flags |= PROXY_ALL_OK;
260 			else
261 			  {
262 			     struct sockaddr_in sa;
263 			     int salen = sizeof(struct sockaddr_in);
264 
265 			     if (getpeername(server_list[j].write, (struct sockaddr *) &sa, &salen) != -1)
266 			       {
267 				  server_list[j].flags |= PROXY_CONNECTED;
268 				  set_blocking(server_list[j].read);
269 				  if (server_list[j].read != server_list[j].write)
270 				    set_blocking(server_list[j].write);
271 			       }
272 			  }
273 		     }
274 		   if (!(server_list[j].flags & SRV_CONNECTED))
275 		     {
276 			if (!socks_proxy)
277 			  {
278 			     struct sockaddr_in sa;
279 			     int salen = sizeof(struct sockaddr_in);
280 
281 			     if (getpeername(server_list[j].write, (struct sockaddr *) &sa, &salen) != -1)
282 			       {
283 				  server_list[j].flags |= SRV_CONNECTED;
284 				  set_blocking(server_list[j].read);
285 				  if (server_list[j].read != server_list[j].write)
286 				    set_blocking(server_list[j].write);
287 			       }
288 			  }
289 			else
290 			  {
291 			     if (!(server_list[j].flags & PROXY_AUTH_OK)
292 				 && !(server_list[j].flags & PROXY_AUTH_SENT))
293 			       {
294 				  /* start socks proxy negotiatons */
295 				  server_list[j].flags |= PROXY_AUTH_SENT;
296 				  if (!socks5_send_auth_req(server_list[j].write))
297 				    {
298 				       close_server(j, NULL);
299 				       server_list[j].connected = server_list[j].in_ping = 0;
300 				       server_list[j].read = server_list[j].write = -1;
301 				    }
302 				  continue;
303 			       }
304 			  }
305 			if (is_ready_for_login(j))
306 			  login_to_server((from_server = j));
307 		     }
308 		}
309 
310 #endif /* NON_BLOCKING_CONNECTS */
311 		if ((des = server_list[j].read) != -1 && FD_ISSET(des, rd))
312 		{
313 			int	junk;
314 			u_char 	*bufptr;
315 			u_char	*s;
316 			int	i = j;
317 #ifdef SUPPORT_ICB
318 			int	old_sep;
319 			int	is_icb = 0;
320 #endif
321 			size_t	len;
322 
323 		   /* do socks proxy stuff if it hasn't been done yet */
324 		   if ((server_list[j].flags & PROXY_AUTH_SENT)
325 		       && !(server_list[j].flags & PROXY_AUTH_OK))
326 		     {
327 			switch (socks5_recv_auth_rep(server_list[j].read))
328 			  {
329 			   case 1:
330 			     server_list[j].flags |= (PROXY_AUTH_OK|PROXY_LOGIN_SENT|PROXY_LOGIN_OK);
331 			     break;
332 			   case 2:
333 			     server_list[j].flags |= (PROXY_AUTH_OK|PROXY_LOGIN_SENT);
334 			     if (socks5_send_userpass_req(server_list[j].read))
335 			       continue;
336 			   default:
337 			     close_server(j, NULL);
338 			     server_list[j].connected = server_list[j].in_ping = 0;
339 			     server_list[j].read = server_list[j].write = -1;
340 			     continue;
341 			  }
342 		     }
343 		   if ((server_list[j].flags & PROXY_LOGIN_SENT)
344 		       && !(server_list[j].flags & PROXY_LOGIN_OK))
345 		     {
346 			if (!socks5_recv_userpass_rep(server_list[j].read))
347 			  {
348 			     close_server(j, NULL);
349 			     server_list[j].connected = server_list[j].in_ping = 0;
350 			     server_list[j].read = server_list[j].write = -1;
351 			     continue;
352 			  }
353 			server_list[j].flags |= PROXY_LOGIN_OK;
354 		     }
355 		   if (socks_proxy
356 		       && (server_list[j].flags & PROXY_LOGIN_OK)
357 		       && !(server_list[j].flags & PROXY_CONNECT_SENT))
358 		     {
359 			struct sockaddr_in ssin;
360 
361 			if (!resolve_host(&ssin.sin_addr, server_list[j].name))
362 			  {
363 			     put_error("Unable to resolve server: %s", server_list[j].name);
364 			     close_server(j, NULL);
365 			     server_list[j].connected = server_list[j].in_ping = 0;
366 			     server_list[j].read = server_list[j].write = -1;
367 			     continue;
368 			  }
369 			ssin.sin_family = AF_INET;
370 			ssin.sin_port = htons(server_list[j].port);
371 			server_list[j].flags |= PROXY_CONNECT_SENT;
372 			if (!socks5_send_connect_req(server_list[j].read, ssin))
373 			  {
374 			     close_server(j, NULL);
375 			     server_list[j].connected = server_list[j].in_ping = 0;
376 			     server_list[j].read = server_list[j].write = -1;
377 			     continue;
378 			  }
379 			continue;
380 		     }
381 		   if (socks_proxy
382 		       && (server_list[j].flags & PROXY_CONNECT_SENT)
383 		       && !(server_list[j].flags & PROXY_CONNECT_OK))
384 		     {
385 			if (!socks5_recv_connect_rep(server_list[j].read))
386 			  {
387 			     close_server(j, NULL);
388 			     server_list[j].connected = server_list[j].in_ping = 0;
389 			     server_list[j].read = server_list[j].write = -1;
390 			  }
391 			server_list[j].flags |= (SRV_CONNECTED|PROXY_CONNECT_OK);
392 			if (is_ready_for_login(j))
393 			  login_to_server(j);
394 			continue;
395 		     }
396 
397 			from_server = i;
398 #ifdef SUPPORT_ICB
399 			is_icb = get_server_version(from_server) == ServerICB;
400 			if (is_icb)
401 				old_sep = dgets_set_separator('\0');
402 #endif
403 
404 			old_timeout = dgets_timeout(1);
405 			s = server_list[from_server].buffer;
406 			bufptr = lbuf;
407 			if (s && *s)
408 			{
409 				len = my_strlen(s);
410 				my_strncpy(lbuf, s, len);
411 				bufptr += len;
412 			}
413 			else
414 				len = 0;
415 			if (len >= BIG_BUFFER_SIZE)
416 				goto buffer_is_full_hack;	/* XXX? */
417 			junk = dgets(bufptr, (int)(BIG_BUFFER_SIZE - len), des, (u_char *) 0);
418 			(void) dgets_timeout(old_timeout);
419 			switch (junk)
420 			{
421 			case -1:
422 				add_to_server_buffer(from_server, lbuf);
423 				goto real_continue;
424 			case 0:
425 			{
426 #ifdef NON_BLOCKING_CONNECTS
427 				int	old_serv = server_list[i].close_serv;
428 			/* Get this here before close_server() clears it -Sol */
429 				int	srv_connected = server_list[i].flags & SRV_CONNECTED;
430 #endif /* NON_BLOCKING_CONNECTS */
431 
432 				close_server(i, empty_string);
433 				say("Connection closed from %s: %s", server_list[i].name,
434 					dgets_errno == -1 ? "Remote end closed connection" : strerror(dgets_errno));
435 				server_list[i].connected = 0;
436 				server_list[i].read = server_list[i].write = -1;
437 
438 			   server_list[i].in_ping = 0;
439 
440 #ifdef NON_BLOCKING_CONNECTS
441 #ifdef SUPPORT_ICB
442 				if (!srv_connected && !is_icb)
443 #else
444 				if (!srv_connected)
445 #endif
446 				{
447 					if (old_serv == i)	/* a hack?  you bet */
448 						goto a_hack;
449 					if (old_serv != -1 && (server_list[old_serv].flags & CLOSE_PENDING))
450 					{
451 						say("Connection to server %s resumed...", server_list[old_serv].name);
452 						server_list[i].close_serv = -1;
453 						server_list[old_serv].flags &= ~(CLOSE_PENDING|CLEAR_PENDING);
454 						server_list[old_serv].flags |= SRV_CONNECTED;
455 						server_list[old_serv].connected = 1;
456 #if 1
457 						get_connected(old_serv);
458 #else
459 						/* get_connected(old_serv);
460 						   should be used only for
461 						   primary_server -Sol */
462 						/* connect_to_server(server_list[old_serv].name, server_list[old_serv].port, server_list[server].nickname, -1);
463 						   actually, do we have to
464 						   reconnect at all ? -Sol */
465 						{ /* Reassign windows ? -Sol */
466 						Window	*tmp;
467 						int	flag = 1;
468 
469 						while ((tmp = traverse_all_windows(&flag)) != (Window *) 0)
470 							if (tmp->server == i)
471 							{
472 								window_set_server(tmp->refnum, old_serv, WIN_ALL);
473 								break;
474 							}
475 						}
476 #endif /* 1 */
477 					}
478 					window_check_servers();
479 					break;
480 				}
481 a_hack:
482 #endif /* NON_BLOCKING_CONNECTS */
483 				if (i == primary_server)
484 				{
485 					if (server_list[i].eof)
486 					{
487 					   say("Unable to connect to server %s",
488 					       server_list[i].name);
489 					   if (++i == number_of_servers)
490 					     {
491 						clean_whois_queue();
492 						window_check_servers();
493 						if (!connected_to_server)
494 						  say("Use /SERVER to connect to a server");
495 						times = 0;
496 					     }
497 					   else
498 					     if (get_int_var(AUTO_RECONNECT_VAR) > 0)
499 					       get_connected(i);
500 					}
501 					else
502 					{
503 					   if (times++ > 1)
504 					     {
505 						clean_whois_queue();
506 						window_check_servers();
507 						if (!connected_to_server)
508 						  say("Use /SERVER to connect to a server");
509 						times = 0;
510 					     }
511 					   else
512 					     if (get_int_var(AUTO_RECONNECT_VAR) > 0)
513 					       get_connected(i);
514 					}
515 				}
516 				else if (server_list[i].eof)
517 				{
518 					say("Connection to server %s lost.", server_list[i].name);
519 					clean_whois_queue();
520 					window_check_servers();
521 				}
522 				else if (connect_to_server(server_list[i].name, server_list[i].port, server_list[i].nickname, -1)) {
523 					say("Connection to server %s lost.", server_list[i].name);
524 					clean_whois_queue();
525 					window_check_servers();
526 				}
527 				server_list[i].eof = 1;
528 				break;
529 			}
530 			default:
531 buffer_is_full_hack:
532 				{
533 					int	old_psi = parsing_server_index;
534 
535 					parsing_server_index = i;
536 					server_list[parsing_server_index].parse_server(lbuf);
537 					new_free(&server_list[i].buffer);
538 					parsing_server_index = old_psi;
539 					break;
540 				}
541 			}
542 real_continue:
543 			from_server = primary_server;
544 #ifdef SUPPORT_ICB
545 			if (is_icb)
546 				(void)dgets_set_separator(old_sep);
547 #endif
548 		}
549 	}
550 }
551 
552 /*
553  * find_in_server_list: given a server name, this tries to match it against
554  * names in the server list, returning the index into the list if found, or
555  * -1 if not found
556  */
557 extern	int
558 find_in_server_list(server, port, nick)
559 	u_char	*server;
560 	int	port;
561 	u_char	*nick;
562 {
563 	int	i, maybe = -1;
564 	size_t	len;
565 
566 	len = my_strlen(server);
567 	for (i = 0; i < number_of_servers; i++)
568 	{
569 		if (port && server_list[i].port &&
570 		    port != server_list[i].port)
571 			continue;
572 
573 		if (my_strnicmp(server, server_list[i].name, len) != 0)
574 			continue;
575 
576 		if (nick)
577 		{
578 			if (server_list[i].nickname == NULL)
579 			{
580 				maybe = i;
581 				continue;
582 			}
583 			if (my_stricmp(server_list[i].nickname, nick))
584 				continue;
585 		}
586 		maybe = i;
587 		break;
588 	}
589 	return (maybe);
590 }
591 
592 /*
593  * parse_server_index:  given a string, this checks if it's a number, and if
594  * so checks it validity as a server index.  Otherwise -1 is returned
595  */
596 int
parse_server_index(str)597 parse_server_index(str)
598 	u_char	*str;
599 {
600    int	i;
601 
602    if (is_number(str))
603      {
604 	i = my_atoi(str);
605 	if ((i > 0) && (i <= number_of_servers))
606 	  return (i-1);
607 	if (i == 0 && number_of_servers > 0)
608 	  return 0;
609      }
610    return (-1);
611 }
612 
613 /*
614  * add_to_server_list: adds the given server to the server_list.  If the
615  * server is already in the server list it is not re-added... however, if the
616  * overwrite flag is true, the port and passwords are updated to the values
617  * passes.  If the server is not on the list, it is added to the end. In
618  * either case, the server is made the current server.
619  */
620 void
add_to_server_list(server,port,password,nick,umode,overwrite)621 add_to_server_list(server, port, password, nick, umode, overwrite)
622 	u_char	*server;
623 	int	port;
624 	u_char	*password;
625 	u_char	*nick;
626 	u_char	*umode;
627 	int	overwrite;
628 {
629 	/* int	i; */
630 
631 	if ((from_server = find_in_server_list(server, port, nick)) == -1)
632 	{
633 		from_server = number_of_servers++;
634 		if (server_list)
635 			server_list = (Server *) new_realloc(UP(server_list), number_of_servers * sizeof(Server));
636 		else
637 			server_list = (Server *) new_malloc(number_of_servers * sizeof(Server));
638 	   /* instead of doin all this bs = 0 crap, lets just do a memset ! */
639 	   memset(&(server_list[from_server]), 0, sizeof(Server));
640 	   /*
641 		server_list[from_server].name = (u_char *) 0;
642 		server_list[from_server].itsname = (u_char *) 0;
643 		server_list[from_server].password = (u_char *) 0;
644 		server_list[from_server].away = (u_char *) 0;
645 		server_list[from_server].version_string = (u_char *) 0;
646 		server_list[from_server].operator = 0;
647 	    */
648 		server_list[from_server].read = -1;
649 		server_list[from_server].write = -1;
650 		server_list[from_server].pid = -1;
651 		/* server_list[from_server].whois = 0; */
652 		server_list[from_server].flags = SERVER_2_6_2;
653 	   /*
654 		server_list[from_server].nickname = (u_char *) 0;
655 		server_list[from_server].connected = 0;
656 		server_list[from_server].eof = 0;
657 	    */
658 		server_list[from_server].motd = 1;
659 	   /*
660 #ifdef SUPPORT_ICB
661 		server_list[from_server].group = (u_char *) 0;
662 		server_list[from_server].icbmode = (u_char *) 0;
663 #endif
664 		server_list[from_server].chan_list = (Channel *) 0;
665 	    */
666 		malloc_strcpy(&(server_list[from_server].name), server);
667 	   if (password && *password)
668 	     malloc_strcpy(&(server_list[from_server].password), password);
669 	   if (nick && *nick)
670 	     malloc_strcpy(&(server_list[from_server].nickname), nick);
671 	   if (umode && *umode)
672 	     dma_strcpy(&(server_list[from_server].usermode), umode);
673 
674 		server_list[from_server].port = port;
675 	   /*
676 		server_list[from_server].WQ_head = (WhoisQueue *) 0;
677 		server_list[from_server].WQ_tail = (WhoisQueue *) 0;
678 		server_list[from_server].whois_stuff.nick = (u_char *) 0;
679 		server_list[from_server].whois_stuff.user = (u_char *) 0;
680 		server_list[from_server].whois_stuff.host = (u_char *) 0;
681 		server_list[from_server].whois_stuff.channel = (u_char *) 0;
682 		server_list[from_server].whois_stuff.channels = (u_char *) 0;
683 		server_list[from_server].whois_stuff.name = (u_char *) 0;
684 		server_list[from_server].whois_stuff.server = (u_char *) 0;
685 		server_list[from_server].whois_stuff.server_stuff = (u_char *) 0;
686 		server_list[from_server].whois_stuff.away = (u_char *) 0;
687 		server_list[from_server].whois_stuff.oper = 0;
688 		server_list[from_server].whois_stuff.chop = 0;
689 		server_list[from_server].whois_stuff.not_on = 0;
690 		server_list[from_server].buffer = (u_char *) 0;
691 	    */
692 		server_list[from_server].close_serv = -1;
693 		/* server_list[from_server].local_addr.s_addr = 0; */
694 #ifdef SUPPORT_ICB
695 		if (connect_next_as_icb || (!connect_next_as_irc && client_default_icb))
696 		{
697 			server_list[from_server].parse_server = icb_parse_server;
698 			server_list[from_server].version = ServerICB;
699 		}
700 		else
701 #endif
702 		{
703 			server_list[from_server].parse_server = irc2_parse_server;
704 			server_list[from_server].version = DEFAULT_SERVER_VERSION;	/* default */
705 		}
706 	   /*
707 		server_list[from_server].ctcp_last_reply_time = 0;
708 		server_list[from_server].ctcp_flood_time = 0;
709 	    */
710 		server_list[from_server].ctcp_backlog_size = get_int_var(CTCP_REPLY_BACKLOG_SECONDS_VAR);
711 		server_list[from_server].ctcp_send_size =
712 			(int *)new_malloc(server_list[from_server].ctcp_backlog_size*sizeof(int));
713 /*
714 		for(i = 0; i<server_list[from_server].ctcp_backlog_size; i++)
715 			server_list[from_server].ctcp_send_size[i] = 0;
716  */
717 	}
718 	else
719 	{
720 		if (overwrite)
721 		{
722 			server_list[from_server].port = port;
723 			if (password || !server_list[from_server].password)
724 			{
725 				if (password && *password)
726 					malloc_strcpy(&(server_list[from_server].password), password);
727 				else
728 					new_free(&(server_list[from_server].password));
729 			}
730 			if (nick && *nick)
731 				malloc_strcpy(&(server_list[from_server].nickname), nick);
732 			if (umode && *umode)
733 				malloc_strcpy(&(server_list[from_server].usermode), umode);
734 		}
735 		if ((int) my_strlen(server) > (int) my_strlen(server_list[from_server].name))
736 			malloc_strcpy(&(server_list[from_server].name), server);
737 	}
738 }
739 
740 extern  void
741 ctcp_reply_backlog_change(s)
742 	int	s;
743 {
744 	int	i, j, delta;
745 
746 	if (s <= 0)
747 		s = 1;
748 	if (server_list)
749 	{
750 		for (i = 0; i < number_of_servers; i++)
751 		{
752 			delta = s - server_list[i].ctcp_backlog_size;
753 
754 			if (delta)
755 			{
756 				server_list[i].ctcp_send_size =
757 					(int *)new_realloc((void *)(server_list[i].ctcp_send_size), s*sizeof(int));
758 				for(j = server_list[i].ctcp_backlog_size; j < s; j++)
759 					server_list[i].ctcp_send_size[j] = 0;
760 				server_list[i].ctcp_backlog_size = s;
761 			}
762 		}
763 	}
764 }
765 
766 extern	void
767 remove_from_server_list(i)
768 	int	i;
769 {
770 	int	old_server = from_server,
771 		flag = 1;
772 	Window	*tmp;
773 
774 	from_server = i;
775 	clean_whois_queue();
776 	from_server = old_server;
777 
778 	close_server(i, (u_char *) 0);
779 
780 	if (server_list[i].name)
781 		new_free(&server_list[i].name);
782 	if (server_list[i].itsname)
783 		new_free(&server_list[i].itsname);
784 	if (server_list[i].password)
785 		new_free(&server_list[i].password);
786 	if (server_list[i].away)
787 		new_free(&server_list[i].away);
788 	if (server_list[i].version_string)
789 		new_free(&server_list[i].version_string);
790 	if (server_list[i].nickname)
791 		new_free(&server_list[i].nickname);
792 	if (server_list[i].usermode)
793 		new_free(&server_list[i].usermode);
794 #ifdef SUPPORT_ICB
795 	if (server_list[i].group)
796 		new_free(&server_list[i].group);
797 	if (server_list[i].icbmode)
798 		new_free(&server_list[i].icbmode);
799 #endif
800 	if (server_list[i].whois_stuff.nick)
801 		new_free(&server_list[i].whois_stuff.nick);
802 	if (server_list[i].whois_stuff.user)
803 		new_free(&server_list[i].whois_stuff.user);
804 	if (server_list[i].whois_stuff.host)
805 		new_free(&server_list[i].whois_stuff.host);
806 	if (server_list[i].whois_stuff.channel)
807 		new_free(&server_list[i].whois_stuff.channel);
808 	if (server_list[i].whois_stuff.channels)
809 		new_free(&server_list[i].whois_stuff.channels);
810 	if (server_list[i].whois_stuff.name)
811 		new_free(&server_list[i].whois_stuff.name);
812 	if (server_list[i].whois_stuff.server)
813 		new_free(&server_list[i].whois_stuff.server);
814 	if (server_list[i].whois_stuff.server_stuff)
815 		new_free(&server_list[i].whois_stuff.server_stuff);
816 	if (server_list[i].ctcp_send_size)
817 		new_free(&server_list[i].ctcp_send_size);
818 
819    dma_Free(&server_list[i].cmodes);
820    dma_Free(&server_list[i].umodes);
821 
822 	/* update all the structs with server in them */
823 	channel_server_delete(i);	/* fix `higher' servers */
824 	clear_channel_list(i);
825 #ifndef _Windows
826 	exec_server_delete(i);
827 #endif /* _Windows */
828 	if (i < primary_server)
829 		--primary_server;
830 	if (i < from_server)
831 		--from_server;
832 	while ((tmp = traverse_all_windows(&flag)) != NULL)
833 		if (tmp->server > i)
834 			tmp->server--;
835 
836 	bcopy((char *) &server_list[i + 1], (char *) &server_list[i], (number_of_servers - i - 1) * sizeof(Server));
837 	server_list = (Server *) new_realloc(UP(server_list), --number_of_servers * sizeof(Server));
838 }
839 
840 /*
841  * parse_server_info:  This parses a single string of the form
842  * "server:portnum:password:nickname".  It the points port to the portnum
843  * portion and password to the password portion.  This chews up the original
844  * string, so * upon return, name will only point the the name.  If portnum
845  * or password are missing or empty,  their respective returned value will
846  * point to null.  if extra is non NULL, it is set to anything after the
847  * final : after the nickname..
848  *
849  * Note:  this will set connect_next_as_irc/connect_next_as_icb if it sees
850  * the IRC/ or ICB/ at the start of the "name".
851  *
852  * 10/10/2001 added umode after nick, before extra.
853  *     -jjd   also made it so :: doesn't mean stop..
854  */
855 void
parse_server_info(name,port,password,nick,umode,extra)856 parse_server_info(name, port, password, nick, umode, extra)
857 	u_char	**name,
858 		**port,
859 		**password,
860 		**nick,
861 		**umode,
862 		**extra;
863 {
864 	u_char *ptr, *ename, *savename = (u_char *) 0;
865 
866 	*port = *password = *nick = *extra = *umode = NULL;
867 #ifdef SUPPORT_ICB
868 	if (my_strncmp(*name, "IRC/", 4) == 0)
869 	{
870 		connect_next_as_irc = 1;
871 		*name += 4;
872 	}
873 	else
874 	if (my_strncmp(*name, "ICB/", 4) == 0)
875 	{
876 		connect_next_as_icb = 1;
877 		*name += 4;
878 	}
879 #endif
880 	/* check for [i:p:v:6]:port style */
881 	if (**name == '[')
882 	{
883 		if ((ename = my_index((*name)+1, ']')))
884 		{
885 			*ename = '\0';
886 			savename = *name + 1;
887 			*name = ename + 1;	/* now points to empty or : we hope */
888 		}
889 	}
890    /* starting here, jduck re-wrote it.. */
891    if ((ptr = my_index(*name, ':')) != NULL)
892      {
893 	*(ptr++) = (u_char) 0;
894 	if (my_strlen(ptr) > 0)
895 	  *port = ptr;
896      }
897    /* check for non-empty port */
898    if (ptr && (ptr = my_index(ptr, ':')) != NULL)
899      {
900 	*(ptr++) = (u_char) 0;
901 	if (my_strlen(ptr) > 0)
902 	  *password = ptr;
903      }
904    /* check for non-empty nick */
905    if (ptr && (ptr = my_index(ptr, ':')) != NULL)
906      {
907 	*(ptr++) = '\0';
908 	if (my_strlen(ptr) > 0)
909 	    *nick = ptr;
910      }
911    /* check for non-empty user mode */
912    if (ptr && (ptr = my_index(ptr, ':')) != NULL)
913      {
914 	*(ptr++) = '\0';
915 	if (my_strlen(ptr) > 0)
916 	  *umode = ptr;
917      }
918    /* check for anything left.. */
919    if (extra &&
920        ptr && (ptr = my_index(ptr, ':')) != NULL)
921      {
922 	*(ptr++) = '\0';
923 	if (my_strlen(ptr) > 0)
924 	  *extra = ptr;
925      }
926    if (savename)
927      *name = savename;
928 }
929 
930 /*
931  * build_server_list: given a whitespace separated list of server names this
932  * builds a list of those servers using add_to_server_list().  Since
933  * add_to_server_list() is used to added each server specification, this can
934  * be called many many times to add more servers to the server list.  Each
935  * element in the server list case have one of the following forms:
936  *
937  * servername
938  *
939  * servername:port
940  *
941  * servername:port:password
942  *
943  * servername::password
944  *
945  * Note also that this routine mucks around with the server string passed to it,
946  * so make sure this is ok .
947  *
948  * A new format for ICB and more support is:
949  *
950  *	type/<type-specifc-format>
951  *
952  * eg:
953  *	IRC/server:port:pass:nick:#foo:#bar:&baz
954  * means connect to server on port port with pass and nick, and then to join
955  * channels #foo, #bar and &baz.  this is not implemented beyond the nick...
956  *
957  * or
958  *	ICB/server:port:pass:nick:group:mode
959  * which is all the things needed at connection startup.  this is done.
960  */
961 void
build_server_list(servers)962 build_server_list(servers)
963 	u_char	*servers;
964 {
965 	u_char	*host,
966 		*rest,
967 		*extra = UNULL,
968 #ifdef SUPPORT_ICB
969 		*mode,
970 #endif
971 		*password = (u_char *) 0,
972 		*port = (u_char *) 0,
973 		*nick = (u_char *) 0,
974 		*umode = UNULL;
975 	int	port_num;
976 
977 	if (servers == (u_char *) 0)
978 		return;
979 	while (servers)
980 	{
981 		if ((rest = my_index(servers, '\n')) != NULL)
982 			*rest++ = '\0';
983 		while ((host = next_arg(servers, &servers)) != NULL)
984 		{
985 			parse_server_info(&host, &port, &password, &nick, &umode, &extra);
986 			if (port && *port)
987 			{
988 				port_num = my_atoi(port);
989 				if (!port_num)
990 					port_num = CHOOSE_PORT;
991 			}
992 			else
993 				port_num = CHOOSE_PORT;
994 			if (!nick)
995 				nick = nickname;
996 			add_to_server_list(host, port_num, password, nick, umode, 0);
997 			if (extra)
998 			{
999 #ifdef SUPPORT_ICB
1000 				if (connect_next_as_icb)
1001 				{
1002 					if ((mode = my_index(extra, ':')) && mode[1])
1003 						*mode++ = 0;
1004 					else
1005 						mode = NULL;
1006 					set_server_icbgroup(from_server, extra);
1007 					set_server_icbmode(from_server, mode);
1008 					connect_next_as_icb = 0;
1009 				}
1010 				if (connect_next_as_irc)
1011 				{
1012 					/* nothing yet */
1013 					connect_next_as_irc = 0;
1014 				}
1015 #endif
1016 			}
1017 		}
1018 		servers = rest;
1019 	}
1020 }
1021 
1022 /*
1023  * connect_to_server_direct: handles the tcp connection to a server.  If
1024  * successful, the user is disconnected from any previously connected server,
1025  * the new server is added to the server list, and the user is registered on
1026  * the new server.  If connection to the server is not successful,  the
1027  * reason for failure is displayed and the previous server connection is
1028  * resumed uniterrupted.
1029  *
1030  * This version of connect_to_server() connects directly to a server
1031  */
1032 static	int
connect_to_server_direct(server_name,port,nick)1033 connect_to_server_direct(server_name, port, nick)
1034 	u_char	*server_name;
1035 	int	port;
1036 	u_char	*nick;
1037 {
1038 	int	new_des;
1039 #ifdef INET6
1040 /*
1041 	struct	sockaddr_storage	localaddr;
1042 */
1043 /* For IPv4 only DCC */
1044 	u_char	strlhost[1025];
1045 	struct	addrinfo h, *r, *r0;
1046 #else
1047 	struct sockaddr_in localaddr;
1048 	int	address_len;
1049 #endif
1050    u_char *socks_proxy = get_string_var(SOCKS_PROXY_VAR);
1051 
1052 	using_server_process = 0;
1053 	oper_command = 0;
1054 	errno = 0;
1055 #ifdef HAVE_SYS_UN_H
1056 	if (*server_name == '/')
1057 		new_des = connect_to_unix(port, server_name);
1058 	else
1059 #endif /* HAVE_SYS_UN_H */
1060      {
1061 	if (socks_proxy)
1062 	  new_des = connect_by_number(SOCKS_PORT, socks_proxy, 1);
1063 	else
1064 	  new_des = connect_by_number(port, server_name, 1);
1065      }
1066 
1067 	if (new_des < 0)
1068 	{
1069 		char *e = NULL;
1070 		switch (new_des)
1071 		{
1072 		default:
1073 		case -2:
1074 			e = "Unknown host";
1075 			errno = 0;
1076 			break;
1077 		case -3:
1078 			e = "socket";
1079 			break;
1080 		case -4:
1081 			e = "connect";
1082 			break;
1083 		}
1084 
1085 	   if (new_des != -5)
1086 	     say("Unable to connect to port %d of %s %s: %s%s%s", port,
1087 		 socks_proxy ? "socks proxy" : "server",
1088 		 socks_proxy ? socks_proxy : server_name,
1089 		 e, errno ? ": " : "", errno ? strerror(errno) : "");
1090 	   if (is_server_open(from_server))
1091 	     say("Connection to server %s resumed...", server_list[from_server].name);
1092 	   return (-1);
1093 	}
1094 #ifdef HAVE_SYS_UN_H
1095 	if (*server_name != '/')
1096 #endif /* HAVE_SYS_UN_H */
1097 	{
1098 #ifndef INET6
1099 		address_len = sizeof(struct sockaddr_in);
1100 		getsockname(new_des, (struct sockaddr *) &localaddr,
1101 				&address_len);
1102 #endif
1103 	}
1104 	update_all_status();
1105 	add_to_server_list(server_name, port, (u_char *) 0, nick, send_umode, 1);
1106 	if (port)
1107 	{
1108 		server_list[from_server].read = new_des;
1109 		server_list[from_server].write = new_des;
1110 	}
1111 	else
1112 		server_list[from_server].read = new_des;
1113 #ifdef INET6
1114 /* DCC works _only_ via IPv4, so we put IPv4 address here */
1115 	gethostname(strlhost, sizeof(strlhost));
1116 	memset(&h, 0, sizeof(h));
1117 	h.ai_family = AF_INET;
1118 	h.ai_socktype = SOCK_STREAM;
1119 	if (getaddrinfo(strlhost, "0", &h, &r0) == 0)
1120 	{
1121 		struct sockaddr_in tmps;
1122 		for (r = r0; r; r = r->ai_next) {
1123 			memcpy(&tmps, r->ai_addr, r->ai_addrlen);
1124 			server_list[from_server].local_addr.s_addr = tmps.sin_addr.s_addr;
1125 			freeaddrinfo(r0);
1126 			break;
1127 		}
1128 	}
1129 #else
1130 	server_list[from_server].local_addr.s_addr = localaddr.sin_addr.s_addr;
1131 #endif
1132 	server_list[from_server].operator = 0;
1133 	return (0);
1134 }
1135 
1136 /*
1137  * connect_to_server_process: handles the tcp connection to a server.  If
1138  * successful, the user is disconnected from any previously connected server,
1139  * the new server is added to the server list, and the user is registered on
1140  * the new server.  If connection to the server is not successful,  the
1141  * reason for failure is displayed and the previous server connection is
1142  * resumed uniterrupted.
1143  *
1144  * This version of connect_to_server() uses the ircio process to talk to a
1145  * server
1146  */
1147 static	int
connect_to_server_process(server_name,port,nick)1148 connect_to_server_process(server_name, port, nick)
1149 	u_char	*server_name;
1150 	int	port;
1151 	u_char	*nick;
1152 {
1153 #ifdef _Windows
1154 	return -1;
1155 #else
1156 	int	write_des[2],
1157 		read_des[2],
1158 		pid,
1159 		c;
1160 	u_char	*path,
1161 		*name = (u_char *) 0,
1162 		*s;
1163 	u_char	buffer[BIG_BUFFER_SIZE];
1164 	int	old_timeout;
1165 
1166 	path = UP(IRCIO_PATH);
1167 	if ((s = my_rindex(path, '/')) != NULL)
1168 		malloc_strcpy(&name, s + 1);
1169 	if (!name)
1170 		name = path;
1171 	if (*path == '\0')
1172 		return (connect_to_server_direct(server_name, port, nick));
1173 	using_server_process = 1;
1174 	oper_command = 0;
1175 	write_des[0] = -1;
1176 	write_des[1] = -1;
1177 	if (pipe(write_des) || pipe(read_des))
1178 	{
1179 		if (write_des[0] != -1)
1180 		{
1181 			new_close(write_des[0]);
1182 			new_close(write_des[1]);
1183 		}
1184 		say("Couldn't start new process: %s", strerror(errno));
1185 		return (connect_to_server_direct(server_name, port, nick));
1186 	}
1187 	switch (pid = fork())
1188 	{
1189 	case -1:
1190 		say("Couldn't start new process: %s\n", strerror(errno));
1191 		return (-1);
1192 	case 0:
1193 		(void) MY_SIGNAL(SIGINT, (sigfunc *)SIG_IGN, 0);
1194 		dup2(read_des[1], 1);
1195 		dup2(write_des[0], 0);
1196 		new_close(read_des[0]);
1197 		new_close(read_des[1]);
1198 		new_close(write_des[0]);
1199 		new_close(write_des[1]);
1200 		sprintf(CP(buffer), "%u", port);
1201 		setuid(getuid());
1202 		execl(CP(path), CP(name), server_name, buffer, (u_char *) 0);
1203 		printf("-5 0\n"); /* -1 - -4 returned by connect_by_number() */
1204 		fflush(stdout);
1205 		_exit(1);
1206 	default:
1207 		new_close(read_des[1]);
1208 		new_close(write_des[0]);
1209 		break;
1210 	}
1211 	old_timeout = dgets_timeout(3);
1212 	c = dgets(buffer, BIG_BUFFER_SIZE, read_des[0], (u_char *) 0);
1213 	(void) dgets_timeout(old_timeout);
1214 	if ((c == 0) || ((c = my_atoi(buffer)) != 0))
1215 	{
1216 		if (c == -5)
1217 			return (connect_to_server_direct(server_name, port, nick));
1218 		else
1219 		{
1220 			u_char *ptr;
1221 
1222 			if ((ptr = my_index(buffer, ' ')) != NULL)
1223 			{
1224 				ptr++;
1225 				if (my_atoi(ptr) > 0)
1226 		say("Unable to connect to port %d of server %s: %s",
1227 			port, server_name, strerror(my_atoi(ptr)));
1228 				else
1229 		say("Unable to connect to port %d of server %s: Unknown host",
1230 							port, server_name);
1231 			}
1232 			else
1233 		say("Unable to connect to port %d of server %s: Unknown host",
1234 							port, server_name);
1235 			if (is_server_open(from_server))
1236 				say("Connection to server %s resumed...",
1237 						server_list[from_server].name);
1238 			new_close(read_des[0]);
1239 			new_close(write_des[1]);
1240 			return (-1);
1241 		}
1242 	}
1243 	update_all_status();
1244 	add_to_server_list(server_name, port, (u_char *) 0, nick, send_umode, 1);
1245 	server_list[from_server].read = read_des[0];
1246 	server_list[from_server].write = write_des[1];
1247 	server_list[from_server].pid = pid;
1248 	server_list[from_server].operator = 0;
1249 	return (0);
1250 #endif /* _Windows */
1251 }
1252 
1253 /*
1254  * connect_to_server: Given a name and portnumber, this will attempt to
1255  * connect to that server using either a direct connection or process
1256  * connection, depending on the value of using_server_process.  If connection
1257  * is successful, the proper NICK, USER, and PASS commands are sent to the
1258  * server.  If the c_server parameter is not -1, then the server with that
1259  * index will be closed upon successful connection here. Also, if connection
1260  * is successful, the attempting_to_connect variable is incremented.  This is
1261  * checked in the notice.c routines to make sure that connection was truely
1262  * successful (and not closed immediately by the server).
1263  */
1264 int
connect_to_server(server_name,port,nick,c_server)1265 connect_to_server(server_name, port, nick, c_server)
1266 	u_char	*server_name;
1267 	int	port;
1268 	u_char	*nick;
1269 	int	c_server;
1270 {
1271 	int	server_index;
1272 #ifdef INET6
1273 	struct	sockaddr_storage	sa;
1274 	int salen = sizeof( struct sockaddr_storage );
1275 #else
1276 	struct sockaddr_in	sa;
1277 	int salen = sizeof( struct sockaddr_in );
1278 #endif
1279 
1280 	save_message_from();
1281 	message_from((u_char *) 0, LOG_CURRENT);
1282 	server_index = find_in_server_list(server_name, port, nick);
1283 	attempting_to_connect = 1;
1284 	/*
1285 	 * check if the server doesn't exist, or that we're not already
1286 	 * connected to it.
1287 	 */
1288 	if (!is_server_connected(server_index))
1289 	{
1290 		if (is_server_open(server_index))
1291 			close_server(server_index, UP("retrying connect"));
1292 		if (port == -1)
1293 		{
1294 			if (server_index >= 0 && server_index < number_of_servers)
1295 				port = server_list[server_index].port;
1296 			else
1297 				port = CHOOSE_PORT;
1298 		}
1299 		say("Connecting to port %d of server %s", port, server_name);
1300 
1301 		load_ircquick();
1302 
1303 		if (using_server_process)
1304 			server_index = connect_to_server_process(server_name, port, nick);
1305 		else
1306 			server_index = connect_to_server_direct(server_name, port, nick);
1307 		if (server_index)
1308 		{
1309 			attempting_to_connect = 0;
1310 			restore_message_from();
1311 			return -1;
1312 		}
1313 		if ((c_server != -1) && (c_server != from_server))
1314 		{
1315 #ifdef NON_BLOCKING_CONNECTS
1316 			/*
1317 			 * this sucks.. we can't keep our channels if the
1318 			 * new server connect() fails.
1319 			 */
1320 #if defined(GKM)
1321 			say("--- server %s will be closed when we connect", server_list[c_server].name);
1322 			if (server_list[c_server].flags & CLOSE_PENDING)
1323 				say("--- why are we flagging this for closing a second time?");
1324 #endif /* GKM */
1325 			server_list[from_server].close_serv = c_server;
1326 			server_list[c_server].flags |= CLOSE_PENDING;
1327 			server_list[c_server].connected = 0;
1328 #else
1329 			close_server(c_server, "changing servers");
1330 #endif /* NON_BLOCKING_CONNECTS */
1331 		}
1332 		else
1333 		{
1334 			server_list[from_server].close_serv = -1;
1335 		}
1336 		if (connect_next_nick)
1337 		{
1338 			if (*connect_next_nick)
1339 				malloc_strcpy(&(server_list[from_server].nickname), connect_next_nick);
1340 			new_free(&connect_next_nick);
1341 		}
1342 		if (connect_next_password)
1343 		{
1344 			if (*connect_next_password)
1345 			malloc_strcpy(&(server_list[from_server].password),
1346 					connect_next_password);
1347 			new_free(&connect_next_password);
1348 		}
1349 	   if (connect_next_umode)
1350 	     {
1351 		if (*connect_next_umode)
1352 		  malloc_strcpy(&(server_list[from_server].usermode), connect_next_umode);
1353 		new_free(&connect_next_umode);
1354 	     }
1355 #ifdef SUPPORT_ICB
1356 		if (connect_next_icbgroup)
1357 		{
1358 			if (*connect_next_icbgroup)
1359 				malloc_strcpy(&(server_list[from_server].group), connect_next_icbgroup);
1360 			new_free(&connect_next_icbgroup);
1361 		}
1362 		if (connect_next_icbmode)
1363 		{
1364 			if (*connect_next_icbmode)
1365 				malloc_strcpy(&(server_list[from_server].icbmode), connect_next_icbmode);
1366 			new_free(&connect_next_icbmode);
1367 		}
1368 #endif
1369 		if (server_list[from_server].nickname == (u_char *) 0)
1370 			malloc_strcpy(&(server_list[from_server].nickname),
1371 					nickname);
1372 
1373 	   if (server_list[from_server].usermode == (u_char *) 0)
1374 	     malloc_strcpy(&(server_list[from_server].usermode), send_umode);
1375 
1376 	   server_list[from_server].flags &= ~(SRV_CONNECTED|PROXY_ALL_OK|LOGGED_IN);
1377 
1378 		/*
1379 		 * this used to be an ifndef NON_BLOCKING_CONNECTS .. we want to do this
1380 		 * whenever the connection is valid, it's possible for a connect to be
1381 		 * "immediate".
1382 		 */
1383 		if (is_server_open(from_server) &&
1384 		    getpeername(server_list[from_server].read, (struct sockaddr *) &sa, &salen) != -1)
1385 	     	{
1386 		   /* blocking now :( */
1387 		   set_blocking(server_list[from_server].read);
1388 		   if (server_list[from_server].read != server_list[from_server].write)
1389 		     set_blocking(server_list[from_server].write);
1390 
1391 		   /* we are connected to something, what is it?? */
1392 		   if (get_string_var(SOCKS_PROXY_VAR))
1393 		     {
1394 			/* start socks proxy negotiatons */
1395 			server_list[from_server].flags |= (PROXY_CONNECTED|PROXY_AUTH_SENT);
1396 			if (!socks5_send_auth_req(server_list[from_server].read))
1397 			  {
1398 			     close_server(from_server, NULL);
1399 			     server_list[from_server].flags |= CLOSE_PENDING;
1400 			     return 0;
1401 			  }
1402 		     }
1403 		   else
1404 		     server_list[from_server].flags |= (PROXY_ALL_OK|SRV_CONNECTED);
1405 		   if (is_ready_for_login(from_server))
1406 		     login_to_server(from_server);
1407 		}
1408 	}
1409 	else
1410 	{
1411 		if (port == -1)
1412 		{
1413 			if (server_index >= 0 && server_index < number_of_servers)
1414 				port = server_list[server_index].port;
1415 			else
1416 				port = CHOOSE_PORT;
1417 		}
1418 		say("Connected to port %d of server %s", port, server_name);
1419 		from_server = server_index;
1420 		if ((c_server != -1) && (c_server != from_server))
1421 			close_server(c_server, UP("changing servers"));
1422 	}
1423 	update_all_status();
1424 	restore_message_from();
1425 	return 0;
1426 }
1427 
1428 static	void
login_to_server(server)1429 login_to_server(server)
1430 	int server;
1431 {
1432 #ifdef NON_BLOCKING_CONNECTS
1433 	int	old_serv = server_list[server].close_serv;
1434 #endif /* NON_BLOCKING_CONNECTS */
1435 
1436    if (server_list[server].flags & LOGGED_IN)
1437      {
1438 	put_error("already tried to login!!");
1439 	return;
1440      }
1441 
1442 	server_list[server].flags |= LOGGED_IN;
1443 
1444 #ifdef NON_BLOCKING_CONNECTS
1445 	if (old_serv != -1)
1446 	{
1447 #if defined(GKM)
1448 		say("--- closing server %s - changing servers", server_list[server_list[server].close_serv].name);
1449 		if (!(server_list[server_list[server].close_serv].flags & CLOSE_PENDING))
1450 			say("--- uh oh. closing a server that wasn't CLOSE_PENDING");
1451 #endif /* GKM */
1452 		if (server_list[old_serv].flags & CLEAR_PENDING)
1453 			clear_channel_list(old_serv);   /* Channels were
1454 							   transfered -Sol */
1455 		server_list[old_serv].flags &= ~(CLOSE_PENDING|CLEAR_PENDING);
1456 		close_server(old_serv, UP("changing servers"));
1457 		server_list[server].close_serv = -1;
1458 		/* should we pause here to let the net catch up with us? */
1459 	}
1460 #if defined(GKM)
1461 	else
1462 	{
1463 		say("--- no server to close in login_to_server()");
1464 	}
1465 #endif /* GKM */
1466 #endif /* NON_BLOCKING_CONNECTS */
1467 #ifdef SUPPORT_ICB
1468 	if (connect_next_as_icb || (!connect_next_as_irc && client_default_icb))
1469 	{
1470 		set_server_version(server, ServerICB);
1471 		icb_login_to_server(server);
1472 	}
1473 	else
1474 #endif
1475 		irc2_login_to_server(server);
1476 #ifdef SUPPORT_ICB
1477 	connect_next_as_icb = 0;
1478 	connect_next_as_irc = 0;
1479 #endif
1480 }
1481 
1482 static	void
irc2_login_to_server(server)1483 irc2_login_to_server(server)
1484 	int	server;
1485 {
1486 
1487 	if (server_list[server].password)
1488 		send_to_server("PASS %s", server_list[server].password);
1489 	send_to_server("NICK %s", server_list[server].nickname);
1490 	send_to_server("USER %s %s %s :%s", username,
1491 		(send_umode && *send_umode) ? send_umode : hostname,
1492 		server_list[server].name, realname);
1493 }
1494 
1495 /*
1496  * get_connected: This function connects the primary server for IRCII.  It
1497  * attempts to connect to the given server.  If this isn't possible, it
1498  * traverses the server list trying to keep the user connected at all cost.
1499  * oldconn is set if this connection is really an old connection being
1500  * resurected (eg. connection to server failed).
1501  */
1502 void
get_connected(server)1503 get_connected(server)
1504 	int	server;
1505 {
1506 	int	s,
1507 		ret = -1;
1508    time_t now;
1509 
1510    time(&now);
1511    s = get_int_var(AUTO_RECONNECT_VAR);
1512    if ((now - last_cnct_attempt) < s)
1513      {
1514 	put_error("AUTO_RECONNECT_DELAY is set to %d, reconnection in %d seconds...",
1515 		  s, s - (now - last_cnct_attempt));
1516 	/* perhaps mark the server for connection or something */
1517 	return;
1518      }
1519    last_cnct_attempt = now;
1520 
1521 	if (server_list)
1522 	{
1523 		int	already_connected = 0;
1524 
1525 		if (server == number_of_servers)
1526 			server = 0;
1527 		else if (server < 0)
1528 			server = number_of_servers - 1;
1529 		s = server;
1530 		if (connect_to_server(server_list[server].name, server_list[server].port, server_list[server].nickname, primary_server))
1531 		{
1532 			while (server_list[server].read == -1)
1533 			{
1534 				server++;
1535 				if (server == number_of_servers)
1536 					server = 0;
1537 				if (server == s)
1538 				{
1539 					clean_whois_queue();
1540 					say("Use /SERVER to connect to a server");
1541 					break;
1542 				}
1543 				from_server = server;
1544 				already_connected = is_server_connected(server);
1545 				ret = connect_to_server(server_list[server].name, server_list[server].port, server_list[server].nickname, primary_server);
1546 			}
1547 			if (!ret)
1548 				from_server = server;
1549 			else
1550 				from_server = -1;
1551 		}
1552 		if (from_server != -1) {
1553 			int flags;
1554 
1555 			flags = (already_connected ? 0 : WIN_TRANSFER);
1556 			window_set_server(-1, from_server, flags);
1557 		}
1558 	}
1559 	else
1560 	{
1561 		clean_whois_queue();
1562 		say("Use /SERVER to connect to a server");
1563 	}
1564 }
1565 
1566 #ifdef SERVERS_FILE
1567 /*
1568  * read_server_file: reads hostname:portnum:password server information from
1569  * a file and adds this stuff to the server list.  See build_server_list()/
1570  */
1571 int
read_server_file()1572 read_server_file()
1573 {
1574 	FILE *fp;
1575 	u_char format[11];
1576 	u_char *file_path = (u_char *) 0;
1577 	u_char	buffer[BIG_BUFFER_SIZE];
1578 
1579 	malloc_strcpy(&file_path, irc_lib);
1580 	malloc_strcat(&file_path, UP(SERVERS_FILE));
1581 	sprintf(CP(format), "%%%ds", BIG_BUFFER_SIZE);
1582 	fp = fopen(CP(file_path), "r");
1583 	new_free(&file_path);
1584 	if ((FILE *) 0 != fp)
1585 	{
1586 		while (fscanf(fp, CP(format), buffer) != EOF)
1587 			build_server_list(buffer);
1588 		fclose(fp);
1589 		return (0);
1590 	}
1591 	return (1);
1592 }
1593 #endif /* SERVERS_FILE */
1594 
1595 /* display_server_list: just guess what this does */
1596 void
display_server_list()1597 display_server_list()
1598 {
1599 	int	i;
1600 
1601 	if (server_list)
1602 	{
1603 		if (from_server != -1)
1604 			say("Current server: %s %d",
1605 					server_list[from_server].name,
1606 					server_list[from_server].port);
1607 		else
1608 			say("Current server: <None>");
1609 		if (primary_server != -1)
1610 			say("Primary server: %s %d",
1611 				server_list[primary_server].name,
1612 				server_list[primary_server].port);
1613 		else
1614 			say("Primary server: <None>");
1615 #ifdef SUPPORT_ICB
1616 		if (client_default_icb)
1617 			say("Using ICB connections by default");
1618 #endif
1619 		say("Server list:");
1620 		for (i = 0; i < number_of_servers; i++)
1621 		{
1622 #ifdef SUPPORT_ICB
1623 			u_char	*icb_msg = server_list[i].version == ServerICB ? (u_char *) " (ICB connection)" : empty_string;
1624 #else
1625 			u_char	*icb_msg = empty_string;
1626 #endif
1627 
1628 			if (!server_list[i].nickname)
1629 			{
1630 				say("\t%d) %s %d%s%s", i+1,
1631 					server_list[i].name,
1632 					server_list[i].port,
1633 					server_list[i].read == -1 ? " (not connected)" : "",
1634 					icb_msg);
1635 			}
1636 			else
1637 			{
1638 				if (server_list[i].read == -1)
1639 					say("\t%d) %s %d (was %s)%s", i+1,
1640 						server_list[i].name,
1641 						server_list[i].port,
1642 						server_list[i].nickname,
1643 						icb_msg);
1644 				else
1645 					say("\t%d) %s %d (%s)%s", i+1,
1646 						server_list[i].name,
1647 						server_list[i].port,
1648 						server_list[i].nickname,
1649 						icb_msg);
1650 			}
1651 #ifdef GKM
1652 			say("\t\tflags: %s%s%s%s%s%s",
1653 				server_list[i].flags & SERVER_2_6_2 ? "SERVER_2_6_2 " : "",
1654 				server_list[i].flags & USER_MODE_I ? "USER_MODE_I " : "",
1655 				server_list[i].flags & USER_MODE_W ? "USER_MODE_W " : "",
1656 				server_list[i].flags & USER_MODE_S ? "USER_MODE_S " : "",
1657 				server_list[i].flags & CLOSE_PENDING ? "CLOSE_PENDING " : "",
1658 				server_list[i].flags & LOGGED_IN ? "LOGGED_IN " : "" );
1659 			say("\t\tclose_serv=%d, connected=%d, read=%d, eof=%d", server_list[i].close_serv, server_list[i].connected, server_list[i].read, server_list[i].eof);
1660 #endif /* GKM */
1661 		}
1662 	}
1663 	else
1664 		say("The server list is empty");
1665 }
1666 
1667 void
MarkAllAway(command,message)1668 MarkAllAway(command, message)
1669 	u_char	*command;
1670 	u_char	*message;
1671 {
1672 	int	old_server;
1673 
1674 	old_server = from_server;
1675 	for (from_server = 0; from_server < number_of_servers; from_server++)
1676 	{
1677 		if (is_server_connected(from_server))
1678 			send_to_server("%s :%s", command, message);
1679 	}
1680 	from_server = old_server;
1681 }
1682 
1683 
1684 /*
1685  * set_server_password: this sets the password for the server with the given
1686  * index.  If password is null, the password for the given server is returned
1687  */
1688 u_char	*
set_server_password(server_index,password)1689 set_server_password(server_index, password)
1690 	int	server_index;
1691 	u_char	*password;
1692 {
1693 
1694 	if (server_list)
1695 	{
1696 		if (password)
1697 			malloc_strcpy(&(server_list[server_index].password), password);
1698 		return (server_list[server_index].password);
1699 	}
1700 	else
1701 		return ((u_char *) 0);
1702 }
1703 
1704 #ifdef SUPPORT_ICB
1705 /*
1706  * ICB support
1707  */
1708 void
set_server_icbgroup(server_index,group)1709 set_server_icbgroup(server_index, group)
1710 	int	server_index;
1711 	u_char	*group;
1712 {
1713 
1714 	malloc_strcpy(&server_list[server_index].group, group);
1715 }
1716 
1717 void
set_server_icbmode(server_index,mode)1718 set_server_icbmode(server_index, mode)
1719 	int	server_index;
1720 	u_char	*mode;
1721 {
1722 
1723 	malloc_strcpy(&server_list[server_index].icbmode, mode);
1724 }
1725 #endif
1726 
1727 /*
1728  * server: the /SERVER command. Read the SERVER help page about
1729  */
1730 /*ARGSUSED*/
1731 void
servercmd(command,args,subargs)1732 servercmd(command, args, subargs)
1733 	u_char	*command,
1734 		*args,
1735 		*subargs;
1736 {
1737 	u_char	*server,
1738 		*port,
1739 		*extra,
1740 #ifdef SUPPORT_ICB
1741 		*newmode,
1742 #endif
1743 		*password = (u_char *) 0,
1744 		*nick = (u_char *) 0,
1745 		*umode = UNULL;
1746 	int	port_num,
1747 		i,
1748 		new_server_flags;
1749 
1750 	if ((server = next_arg(args, &args)) != NULL)
1751 	{
1752 		while (*server == '-')
1753 		{
1754 			size_t	len;
1755 
1756 			/*
1757 			 * old usage of `/server -' handled here.
1758 			 */
1759 			if (*++server == '\0')
1760 			{
1761 				get_connected(primary_server - 1);
1762 				return;
1763 			}
1764 			upper(server);
1765 			len = my_strlen(server);
1766 			/*
1767 			 * just don't return if you want to perform some action in one of
1768 			 * the flag handling sections.
1769 			 */
1770 #ifdef SUPPORT_ICB
1771 			if (!my_strncmp(server, "ICB", len))
1772 				connect_next_as_icb = 1;
1773 			else if (!my_strncmp(server, "IRC", len))
1774 				connect_next_as_irc = 1;
1775 			else
1776 #endif
1777 		     	if (!my_strncmp(server, "DELETE", len))
1778 			{
1779 			   if ((server = next_arg(args, &args)) != NULL)
1780 			     removeserver("REMS", server, NULL);
1781 			   /*
1782 					if ((i = parse_server_index(server)) == -1)
1783 					{
1784 						if (-1 == (i = find_in_server_list(server, 0, 0)))
1785 						{
1786 							say("No such server in list");
1787 							return;
1788 						}
1789 					}
1790 					if (server_list[i].connected)
1791 					{
1792 						say("Can not delete server that is already open");
1793 						return;
1794 					}
1795 					remove_from_server_list(i);
1796 					return;
1797 				}
1798 				say("Need server number for -DELETE");
1799 			    */
1800 			   return;
1801 			}
1802 			else if (!my_strncmp(server, "ADD", len))
1803 		     	{
1804 			   if ((server = next_arg(args, &args)) != NULL)
1805 			     addserver("ADDS", server, NULL);
1806 		     	}
1807 			else
1808 			{
1809 				say("SERVER: %s is an unknown flag", server);
1810 				return;
1811 			}
1812 			if ((server = next_arg(args, &args)) == NULL)
1813 			{
1814 				say("SERVER: need a server name");
1815 				return;
1816 			}
1817 		}
1818 
1819 		if (my_index(server, ':') != NULL)
1820 		{
1821 			parse_server_info(&server, &port, &password, &nick, &umode, &extra);
1822 			if (!my_strlen(server))
1823 			{
1824 				say("Server name required");
1825 				return;
1826 			}
1827 			if (port && *port) {
1828 				port_num = my_atoi(port);
1829 				if (!port_num)
1830 					port_num = CHOOSE_PORT;
1831 			} else
1832 				port_num = CHOOSE_PORT;
1833 		}
1834 		else
1835 		{
1836 			if ((port = next_arg(args, &args)) != NULL)
1837 			{
1838 				port_num = my_atoi(port);
1839 				if (!port_num)
1840 					port_num = CHOOSE_PORT;
1841 				if ((password = next_arg(args, &args)) != NULL)
1842 					nick = next_arg(args, &args);
1843 			}
1844 			else
1845 				port_num = CHOOSE_PORT;
1846 
1847 			extra = (u_char *) 0;
1848 		}
1849 
1850 		if (nick && *nick)
1851 			malloc_strcpy(&connect_next_nick, nick);
1852 		if (password && *password)
1853 			malloc_strcpy(&connect_next_password, password);
1854 		if (umode && *umode)
1855 			malloc_strcpy(&connect_next_umode, umode);
1856 
1857 #ifdef SUPPORT_ICB
1858 		if (extra && connect_next_as_icb)
1859 		{
1860 			if ((newmode = my_index(extra, ':')))
1861 			{
1862 				*newmode++ = 0;
1863 				malloc_strcpy(&connect_next_icbmode, newmode);
1864 			}
1865 			malloc_strcpy(&connect_next_icbgroup, extra);
1866 		}
1867 #endif
1868 		if (*server == '+' || *server == '=' || *server == '~')
1869 		{
1870 			if (*(server+1))
1871 			{
1872 				u_char	servinfo[INPUT_BUFFER_SIZE+1];
1873 
1874 				if (*server == '+')
1875 					server++;
1876 				/* Reconstitute whole server info so
1877 				  window_get_connected can parse it -Sol */
1878 				sprintf(CP(servinfo), "%s:%d:%s:%s",
1879 					server, port_num,
1880 					password ? password : empty_string,
1881 					nick ? nick : empty_string);
1882 				window_get_connected(curr_scr_win, servinfo, -1, (u_char *) 0);
1883 			}
1884 			else
1885 				get_connected(primary_server + 1);
1886 			return;
1887 		}
1888 		/*
1889 		 * work in progress.. window->prev_server needs to be set for
1890 		 * all windows that used to be associated with a server as it
1891 		 * switches [successfully] to a new server.
1892 		 * this'll be fun since that can happen in server.c and
1893 		 * window.c and non-blocking-connects will throw yet another
1894 		 * wrench into things since we only want it to happen on
1895 		 * a successful connect. - gkm
1896 		 */
1897 		else if (*server == '.')
1898 		{
1899 			if (*(++server))
1900 			{
1901 				say("syntax error - nothing may be specified after the '.'");
1902 				return;
1903 			}
1904 			if (current_screen && curr_scr_win && curr_scr_win->prev_server != -1)
1905 			{
1906 				window_restore_server(curr_scr_win->prev_server);
1907 				window_get_connected(curr_scr_win, NULL, curr_scr_win->server, (u_char *) 0);
1908 			}
1909 			else
1910 				say("No server previously in use in this window");
1911 			return;
1912 		}
1913 		if ((i = parse_server_index(server)) != -1)
1914 		{
1915 			server = server_list[i].name;
1916 			if (server_list[i].port != -1)
1917 				port_num = server_list[i].port;
1918 			if (server_list[i].nickname && !nick)
1919 				nick = server_list[i].nickname;
1920 		}
1921 		else
1922 			i = find_in_server_list(server, port_num, nick);
1923 		if (is_server_connected(i))
1924 		{
1925 			/*
1926 			 * We reset the log level only if the "new" server
1927 			 * already has windows associated with it : here it's
1928 			 * equivalent to its already being connected. -Sol
1929 			 */
1930 			new_server_flags = 0;
1931 		}
1932 		else
1933 			new_server_flags = WIN_TRANSFER;
1934 		if (connect_to_server(server, port_num, nick, primary_server) != -1)
1935 		{
1936 			if (primary_server > -1 && from_server != primary_server &&
1937 			    !server_list[from_server].away && server_list[primary_server].away)
1938 				malloc_strcpy(&server_list[from_server].away, server_list[primary_server].away);
1939 			window_set_server(-1, from_server, new_server_flags);
1940 		}
1941 	}
1942 	else
1943 		display_server_list();
1944 }
1945 
1946 /*
1947  * flush_server: eats all output from server, until there is at least a
1948  * second delay between bits of servers crap... useful to abort a /links.
1949  */
1950 void
flush_server()1951 flush_server()
1952 {
1953 	fd_set rd;
1954 	struct timeval time_out;
1955 	int	flushing = 1;
1956 	int	des;
1957 	int	old_timeout;
1958 	u_char	buffer[BIG_BUFFER_SIZE];
1959 
1960 	if ((des = server_list[from_server].read) == -1)
1961 		return;
1962 	time_out.tv_usec = 0;
1963 	time_out.tv_sec = 1;
1964 	old_timeout = dgets_timeout(1);
1965 	while (flushing)
1966 	{
1967 		FD_ZERO(&rd);
1968 		FD_SET(des, &rd);
1969 		switch (new_select(&rd, (fd_set *) 0, &time_out))
1970 		{
1971 		case -1:
1972 		case 0:
1973 			flushing = 0;
1974 			break;
1975 		default:
1976 			if (FD_ISSET(des, &rd))
1977 			{
1978 				if (0 == dgets(buffer, BIG_BUFFER_SIZE, des,
1979 						(u_char *) 0))
1980 					flushing = 0;
1981 
1982 			}
1983 			break;
1984 		}
1985 	}
1986 	/* make sure we've read a full line from server */
1987 	FD_ZERO(&rd);
1988 	FD_SET(des, &rd);
1989 	if (new_select(&rd, (fd_set *) 0, &time_out) > 0)
1990 		dgets(buffer, BIG_BUFFER_SIZE, des, (u_char *) 0);
1991 	(void) dgets_timeout(old_timeout);
1992 }
1993 
1994 /*
1995  * set_server_whois: sets the whois value for the given server index.  If the
1996  * whois value is 0, it assumes the server doesn't send End of WHOIS commands
1997  * and the whois.c routines use the old fashion way of getting whois info. If
1998  * the whois value is non-zero, then the server sends End of WHOIS and things
1999  * can be done more effienciently
2000  */
2001 void
set_server_whois(server_index,value)2002 set_server_whois(server_index, value)
2003 	int	server_index,
2004 		value;
2005 {
2006 	server_list[server_index].whois = value;
2007 }
2008 
2009 /* get_server_whois: Returns the whois value for the given server index */
2010 int
get_server_whois(server_index)2011 get_server_whois(server_index)
2012 	int	server_index;
2013 {
2014 	if (server_index < 0 || server_index >= number_of_servers)
2015 		server_index = primary_server;
2016 	return (server_list[server_index].whois);
2017 }
2018 
2019 
2020 void
set_server_2_6_2(server_index,value)2021 set_server_2_6_2(server_index, value)
2022 	int	server_index,
2023 		value;
2024 {
2025 	set_server_flag(server_index, SERVER_2_6_2, value);
2026 }
2027 
2028 int
get_server_2_6_2(server_index)2029 get_server_2_6_2(server_index)
2030 	int	server_index;
2031 {
2032 	if (server_index < 0 || server_index >= number_of_servers)
2033 		server_index = primary_server;
2034 	return (get_server_flag(server_index, SERVER_2_6_2));
2035 }
2036 
2037 void
set_server_flag(server_index,flag,value)2038 set_server_flag(server_index, flag, value)
2039 	int	server_index;
2040 	int	flag;
2041 	int	value;
2042 {
2043 	if (server_index < 0 || server_index >= number_of_servers)
2044 		server_index = primary_server;
2045 	if (value)
2046 		server_list[server_index].flags |= flag;
2047 	else
2048 		server_list[server_index].flags &= ~flag;
2049 }
2050 
2051 int
get_server_flag(server_index,value)2052 get_server_flag(server_index, value)
2053 	int	server_index;
2054 	int	value;
2055 {
2056 	if (server_index < 0 || server_index >= number_of_servers)
2057 		server_index = primary_server;
2058 	return server_list[server_index].flags & value;
2059 }
2060 
2061 #ifdef SUPPORT_ICB
2062 /* get ICB group */
2063 u_char *
get_server_icbgroup(server_index)2064 get_server_icbgroup(server_index)
2065 	int	server_index;
2066 {
2067 	u_char	*group;
2068 
2069 	if (server_index < 0 || server_index >= number_of_servers)
2070 		server_index = primary_server;
2071 	group = server_list[server_index].group ? server_list[server_index].group : empty_string;
2072 	return (group);
2073 }
2074 
2075 /* get ICB mode */
2076 u_char *
get_server_icbmode(server_index)2077 get_server_icbmode(server_index)
2078 	int	server_index;
2079 {
2080 	u_char	*mode;
2081 
2082 	if (server_index < 0 || server_index >= number_of_servers)
2083 		server_index = primary_server;
2084 	mode = server_list[server_index].icbmode ? server_list[server_index].icbmode : empty_string;
2085 	return (mode);
2086 }
2087 #endif
2088 
2089 /*
2090  * get_server_password: get the passwor for this server.
2091  */
2092 u_char *
get_server_password(server_index)2093 get_server_password(server_index)
2094 	int	server_index;
2095 {
2096 	if (server_index < 0 || server_index >= number_of_servers)
2097 		server_index = primary_server;
2098 	return (server_list[server_index].password);
2099 }
2100 
2101 /*
2102  * set_server_version: Sets the server version for the given server type.  A
2103  * zero version means pre 2.6, a one version means 2.6 aso. (look server.h
2104  * for typedef)
2105  */
2106 void
set_server_version(server_index,version)2107 set_server_version(server_index, version)
2108 	int	server_index;
2109 	int	version;
2110 {
2111 	if (server_index < 0 || server_index >= number_of_servers)
2112 		server_index = primary_server;
2113 	server_list[server_index].version = version;
2114 }
2115 
2116 /*
2117  * get_server_version: returns the server version value for the given server
2118  * index
2119  */
2120 int
get_server_version(server_index)2121 get_server_version(server_index)
2122 	int	server_index;
2123 {
2124 	if (server_index < 0 || server_index >= number_of_servers)
2125 		server_index = primary_server;
2126 	if (server_index < 0 || server_index >= number_of_servers)
2127 		return DEFAULT_SERVER_VERSION;
2128 	else
2129 		return (server_list[server_index].version);
2130 }
2131 
2132 /* get_server_name: returns the name for the given server index */
2133 u_char	*
get_server_name(server_index)2134 get_server_name(server_index)
2135 	int	server_index;
2136 {
2137 	if (server_index < 0 || server_index >= number_of_servers)
2138 		server_index = primary_server;
2139 	return (server_list[server_index].name);
2140 }
2141 
2142 /* set_server_itsname: returns the server's idea of its name */
2143 u_char	*
get_server_itsname(server_index)2144 get_server_itsname(server_index)
2145 	int	server_index;
2146 {
2147 	if (server_index < 0 || server_index >= number_of_servers)
2148 		server_index = primary_server;
2149 	if (server_list[server_index].itsname)
2150 		return server_list[server_index].itsname;
2151 	else if (server_list[server_index].name)
2152 		return server_list[server_index].name;
2153 	else
2154 		return UP("<None>");
2155 }
2156 
2157 void
set_server_itsname(server_index,name)2158 set_server_itsname(server_index, name)
2159 	int	server_index;
2160 	u_char	*name;
2161 {
2162 	if (server_index < 0 || server_index >= number_of_servers)
2163 		server_index = primary_server;
2164 	malloc_strcpy(&server_list[server_index].itsname, name);
2165 }
2166 
2167 /*
2168  * is_server_open: Returns true if the given server index represents a server
2169  * with a live connection, returns false otherwise
2170  */
2171 int
is_server_open(server_index)2172 is_server_open(server_index)
2173 	int	server_index;
2174 {
2175 	if (server_index < 0 || server_index >= number_of_servers)
2176 		return (0);
2177 	return (server_list[server_index].read != -1);
2178 }
2179 
2180 /*
2181  * is_server_connected: returns true if the given server is connected.  This
2182  * means that both the tcp connection is open and the user is properly
2183  * registered
2184  */
2185 int
is_server_connected(server_index)2186 is_server_connected(server_index)
2187 	int	server_index;
2188 {
2189 	if (server_index < 0 || server_index >= number_of_servers)
2190 		return (0);
2191 	return (server_list[server_index].connected && (server_list[server_index].flags & LOGGED_IN));
2192 }
2193 
2194 /* get_server_port: Returns the connection port for the given server index */
2195 int
get_server_port(server_index)2196 get_server_port(server_index)
2197 	int	server_index;
2198 {
2199 	if (server_index < 0 || server_index >= number_of_servers)
2200 		server_index = primary_server;
2201 	return (server_list[server_index].port);
2202 }
2203 
2204 /*
2205  * get_server_nickname: returns the current nickname for the given server
2206  * index
2207  */
2208 u_char	*
get_server_nickname(server_index)2209 get_server_nickname(server_index)
2210 	int	server_index;
2211 {
2212    if (server_index < 0
2213        || server_index >= number_of_servers
2214        || !server_list[server_index].nickname)
2215      return (nickname);
2216    return (server_list[server_index].nickname);
2217 }
2218 
2219 
2220 
2221 /* get_server_qhead - get the head of the whois queue */
2222 WhoisQueue *
get_server_qhead(server_index)2223 get_server_qhead(server_index)
2224 	int	server_index;
2225 {
2226 	if (server_index >= 0 && server_index < number_of_servers)
2227 		return server_list[server_index].WQ_head;
2228 	else
2229 		return WQ_head;
2230 }
2231 
2232 /* get_server_whois_stuff */
2233 WhoisStuff *
get_server_whois_stuff(server_index)2234 get_server_whois_stuff(server_index)
2235 	int	server_index;
2236 {
2237 	if (server_index < 0 || server_index >= number_of_servers)
2238 		server_index = primary_server;
2239 	return &server_list[server_index].whois_stuff;
2240 }
2241 
2242 /* get_server_qtail - get the tail of the whois queue */
2243 WhoisQueue *
get_server_qtail(server_index)2244 get_server_qtail(server_index)
2245 	int	server_index;
2246 {
2247 	if (server_index >= 0 && server_index < number_of_servers)
2248 		return server_list[server_index].WQ_tail;
2249 	else
2250 		return WQ_tail;
2251 }
2252 
2253 
2254 
2255 /* set_server_qhead - set the head of the whois queue */
2256 void
set_server_qhead(server_index,value)2257 set_server_qhead(server_index, value)
2258 	int	server_index;
2259 	WhoisQueue *value;
2260 {
2261 	if (server_index >= 0 && server_index < number_of_servers)
2262 		server_list[server_index].WQ_head = value;
2263 	else
2264 		WQ_head = value;
2265 }
2266 
2267 /* set_server_qtail - set the tail of the whois queue */
2268 void
set_server_qtail(server_index,value)2269 set_server_qtail(server_index, value)
2270 	int	server_index;
2271 	WhoisQueue *value;
2272 {
2273 	if (server_index >= 0 && server_index < number_of_servers)
2274 		server_list[server_index].WQ_tail = value;
2275 	else
2276 		WQ_tail = value;
2277 }
2278 
2279 
2280 
2281 /*
2282  * get_server_operator: returns true if the user has op privs on the server,
2283  * false otherwise
2284  */
2285 int
get_server_operator(server_index)2286 get_server_operator(server_index)
2287 	int	server_index;
2288 {
2289    if (server_index >= 0 && server_index < number_of_servers)
2290 	return (server_list[server_index].operator);
2291    return 0;
2292 }
2293 
2294 /*
2295  * set_server_operator: If flag is non-zero, marks the user as having op
2296  * privs on the given server.
2297  */
2298 void
set_server_operator(server_index,flag)2299 set_server_operator(server_index, flag)
2300 	int	server_index;
2301 	int	flag;
2302 {
2303    if (server_index >= 0 && server_index < number_of_servers)
2304 	server_list[server_index].operator = flag;
2305 }
2306 
2307 /*
2308  * set_server_nickname: sets the nickname for the given server to nickname.
2309  * This nickname is then used for all future connections to that server
2310  * (unless changed with NICK while connected to the server
2311  */
2312 void
set_server_nickname(server_index,nick)2313 set_server_nickname(server_index, nick)
2314 	int	server_index;
2315 	u_char	*nick;
2316 {
2317 	if (server_index >= 0 && server_index < number_of_servers)
2318 	{
2319 		malloc_strcpy(&(server_list[server_index].nickname), nick);
2320 		if (server_index == primary_server)
2321 			malloc_strcpy(&nickname, nick);
2322 	   /* what if we're trying to get lag info??
2323 	    * force re-check..
2324 	    */
2325 	   if (server_list[server_index].in_ping)
2326 	     do_server_lag_check(server_index, time(NULL));
2327 	}
2328 	update_all_status();
2329 }
2330 
2331 void
set_server_motd(server_index,flag)2332 set_server_motd(server_index, flag)
2333 	int	server_index;
2334 	int	flag;
2335 {
2336    if (server_index >= 0 && server_index < number_of_servers)
2337 		server_list[server_index].motd = flag;
2338 }
2339 
2340 int
get_server_motd(server_index)2341 get_server_motd(server_index)
2342 	int	server_index;
2343 {
2344    if (server_index >= 0 && server_index < number_of_servers)
2345 		return(server_list[server_index].motd);
2346 	return (0);
2347 }
2348 
2349 void
server_is_connected(server_index,value)2350 server_is_connected(server_index, value)
2351 	int	server_index,
2352 		value;
2353 {
2354    if (server_index >= 0 && server_index < number_of_servers)
2355      server_list[server_index].connected = value;
2356 	if (value)
2357 		server_list[server_index].eof = 0;
2358 }
2359 
2360 extern int in_redirect;
2361 /* send_to_server: sends the given info the the server */
2362 void
2363 #ifdef HAVE_STDARG_H
send_to_server(char * format,...)2364 send_to_server(char *format, ...)
2365 #else
2366 send_to_server(format, arg1, arg2, arg3, arg4, arg5,
2367 		arg6, arg7, arg8, arg9, arg10)
2368 	char	*format;
2369 	char	*arg1,
2370 		*arg2,
2371 		*arg3,
2372 		*arg4,
2373 		*arg5,
2374 		*arg6,
2375 		*arg7,
2376 		*arg8,
2377 		*arg9,
2378 		*arg10;
2379 #endif /* HAVE_STDARG_H */
2380 {
2381 	static	int	in_send_to_server = 0;
2382 	u_char	lbuf[BIG_BUFFER_SIZE + 1];	/* make this buffer *much*
2383 						 * bigger than needed */
2384 	u_char	*buf = lbuf;
2385 	int	des;
2386 	size_t	len;
2387 	int	server = from_server;
2388 #ifdef HAVE_STDARG_H
2389 	va_list vlist;
2390 
2391 	va_start(vlist, format);
2392 #endif /* HAVE_STDARG_H */
2393 
2394 	if (in_send_to_server)
2395 		return;
2396 	bzero(lbuf, sizeof(lbuf));
2397 	in_send_to_server = 1;
2398 	if (server == -1)
2399 		server = primary_server;
2400 	if (server != -1 && ((des = server_list[server].write) != -1) &&
2401 	    (server_list[server].flags & LOGGED_IN) )
2402 	{
2403 		/* save space for the packet length */
2404 #ifdef SUPPORT_ICB
2405 		if (get_server_version(server) == ServerICB)
2406 			buf++;
2407 #endif
2408 		server_list[server].sent = 1;
2409 #ifdef HAVE_STDARG_H
2410 		vsprintf(CP(buf), format, vlist);
2411 		va_end(vlist);
2412 #else
2413 
2414 		sprintf(CP(buf), format, arg1, arg2, arg3, arg4, arg5,
2415 		    arg6, arg7, arg8, arg9, arg10);
2416 #endif /* HAVE_STDARG_H */
2417 		len = my_strlen(buf);
2418 		if (len > (IRCD_BUFFER_SIZE - 2))
2419 			lbuf[IRCD_BUFFER_SIZE - 2] = (u_char) 0;
2420 		/*
2421 		 * for ICB, we send a final nul, and for IRC, we have
2422 		 * a final newline.
2423 		 */
2424 		len++;
2425 #ifdef SUPPORT_ICB
2426 		if (get_server_version(server) == ServerICB)
2427 		{
2428 			/*
2429 			 * we depend on our caller to split things
2430 			 * up for the ICB server
2431 			 */
2432 			if (len > 254)
2433 				len = 254;
2434 			lbuf[len] = 0;
2435 			lbuf[0] = (u_char)len;
2436 			lbuf[++len] = 0;
2437 		}
2438 		else
2439 #endif
2440 			my_strmcat(buf, "\n", IRCD_BUFFER_SIZE);
2441 		send(des, CP(lbuf), len, 0);
2442 	}
2443 	else if (!in_redirect && !connected_to_server)
2444 		say("You are not connected to a server, use /SERVER to connect.");
2445 	in_send_to_server = 0;
2446 }
2447 
2448 #ifdef HAVE_SYS_UN_H
2449 /*
2450  * Connect to a UNIX domain socket. Only works for servers.
2451  * submitted by Avalon for use with server 2.7.2 and beyond.
2452  */
2453 int
connect_to_unix(port,path)2454 connect_to_unix(port, path)
2455 	int	port;
2456 	u_char	*path;
2457 {
2458 	struct	sockaddr_un un;
2459 	int	    sock;
2460 
2461 	sock = socket(AF_UNIX, SOCK_STREAM, 0);
2462 
2463 	un.sun_family = AF_UNIX;
2464 	sprintf(un.sun_path, "%-.100s/%-.6d", path, port);
2465 
2466 	if (connect(sock, (struct sockaddr *)&un, (int)my_strlen(path)+2) == -1)
2467 	{
2468 		new_close(sock);
2469 		return -1;
2470 	}
2471 	return sock;
2472 }
2473 #endif /* HAVE_SYS_UN_H */
2474 
2475 /*
2476  * close_all_server: Used whn creating new screens to close all the open
2477  * server connections in the child process...
2478  */
2479 extern	void
close_all_server()2480 close_all_server()
2481 {
2482 	int	i;
2483 
2484 	for (i = 0; i < number_of_servers; i++)
2485 	{
2486 		if (server_list[i].read != -1)
2487 			new_close(server_list[i].read);
2488 		if (server_list[i].write != -1)
2489 			new_close(server_list[i].write);
2490 	}
2491 }
2492 
2493 extern	u_char	*
create_server_list()2494 create_server_list()
2495 {
2496 	int	i;
2497 	u_char	*value = (u_char *) 0;
2498 	u_char	buffer[BIG_BUFFER_SIZE];
2499 
2500 	*buffer = '\0';
2501 	for (i = 0; i < number_of_servers; i++)
2502 		if (server_list[i].read != -1)
2503 		{
2504 			my_strcat(buffer, get_server_itsname(i));
2505 			my_strcat(buffer, " ");
2506 		}
2507 	malloc_strcpy(&value, buffer);
2508 
2509 	return value;
2510 }
2511 
2512 static	void
add_to_server_buffer(server,buf)2513 add_to_server_buffer(server, buf)
2514 	int	server;
2515 	u_char	*buf;
2516 {
2517 	if (buf && *buf)
2518 	{
2519 		if (server_list[server].buffer)
2520 			malloc_strcat(&server_list[server].buffer, buf);
2521 		else
2522 			malloc_strcpy(&server_list[server].buffer, buf);
2523 	}
2524 }
2525 
2526 void
disconnectcmd(command,args,subargs)2527 disconnectcmd(command, args, subargs)
2528 	u_char	*command,
2529 		*args,
2530 		*subargs;
2531 {
2532 	u_char	*server;
2533 	u_char	*message;
2534 	int	i;
2535 
2536 	if ((server = next_arg(args, &args)) != NULL && server[0] != '*' && server[1] != '\0')
2537 	{
2538 		i = parse_server_index(server);
2539 		if (-1 == i)
2540 		{
2541 			say("No such server!");
2542 			return;
2543 		}
2544 	}
2545 	else
2546 		i = get_window_server(0);
2547 	/*
2548 	 * XXX - this is a major kludge.  i should never equal -1 at
2549 	 * this point.  we only do this because something has gotten
2550 	 * *really* confused at this point.  .mrg.
2551 	 */
2552 	if (i == -1)
2553 	{
2554 		for (i = 0; i < number_of_servers; i++)
2555 		{
2556 			server_list[i].eof = -1;
2557 			new_close(server_list[i].read);
2558 			new_close(server_list[i].write);
2559 		}
2560 		goto done;
2561 	}
2562 	if (!args || !*args)
2563 		message = UP("l8r");
2564 	else
2565 		message = args;
2566 	if (-1 == server_list[i].write)
2567 	{
2568 		say("That server isn't connected!");
2569 		return;
2570 	}
2571 	server = server_list[i].itsname ? server_list[i].itsname :
2572 		server_list[i].name ? server_list[i].name : (u_char *) "unknown?";
2573 	say("Disconnecting from server %s", server);
2574 	close_server(i, message);
2575 	server_list[i].eof = 1;
2576 done:
2577 	clean_whois_queue();
2578 	window_check_servers();
2579 	if (!connected_to_server)
2580 		say("You are not connected to a server. Use /SERVER to connect.");
2581 }
2582 
2583 int
find_server_group(group,add)2584 find_server_group(group, add)
2585 	u_char	*group;
2586 	int	add;
2587 {
2588 	static	int	next = 1;
2589 	SGroup *g = (SGroup *) find_in_list((List **) &server_group_list, group, 0);
2590 
2591 	if (g)
2592 		goto end;
2593 
2594 	if (!add)
2595 		return 0;
2596 
2597 	g = (SGroup *) new_malloc(sizeof(SGroup));
2598 	g->name = (u_char *) 0;
2599 	malloc_strcpy(&g->name, group);
2600 	g->number = next++;
2601 	add_to_list((List **) &server_group_list, (List *) g);
2602 end:
2603 	return g->number;
2604 }
2605 
2606 u_char	*
find_server_group_name(number)2607 find_server_group_name(number)
2608 	int	number;
2609 {
2610 	SGroup *g = server_group_list;
2611 
2612 	for (; g; g = g->next)
2613 		if (g->number == number)
2614 			return g->name;
2615 	return empty_string;
2616 }
2617 
2618 /* ninja /reconnect command */
2619 void
reconnect(command,args,subargs)2620 reconnect(command, args, subargs)
2621    u_char *command, *args, *subargs;
2622 {
2623    if (is_server_connected(from_server))
2624      {
2625 	close_server(from_server, "brb");
2626 	get_connected(from_server);
2627      }
2628    else
2629       put_error("You are not connected to a server!");
2630 }
2631 
2632 /*
2633  * returns the server's lag
2634  */
2635 int
get_server_lag(int server_index)2636 get_server_lag(int server_index)
2637 {
2638    if (server_index < 0 || server_index >= number_of_servers)
2639      return 0;
2640    if (server_list[server_index].in_ping)
2641      return time(NULL) - server_list[server_index].lag_time;
2642    return (server_list[server_index].lag);
2643 }
2644 
2645 /*
2646  * this should move to server.c sometime soon
2647  */
2648 void
set_server_lag(snum)2649 set_server_lag(snum)
2650    int snum;
2651 {
2652    time_t current = time(NULL);
2653 
2654    if (snum < 0 || snum >= number_of_servers)
2655      return;
2656    server_list[snum].lag = current - server_list[snum].lag_time;
2657 #ifdef DEBUG_SERVER_LAG
2658    put_info("set server #%u lag to %u at %s..", snum, server_list[snum].lag, ninja_ctime(&current));
2659 #endif
2660    server_list[snum].in_ping = 0;
2661    update_all_status();
2662 }
2663 
2664 
2665 /*
2666  * set_server_usermode: sets the usermode for the given server to umode.
2667  * This user mode is then used for all future connections to that server
2668  * (unless changed with MODE while connected to the server)
2669  */
2670 void
set_server_usermode(server_index,umode)2671 set_server_usermode(server_index, umode)
2672 	int	server_index;
2673 	u_char	*umode;
2674 {
2675    if (server_index >= 0 && server_index < number_of_servers)
2676      {
2677 	malloc_strcpy(&(server_list[server_index].usermode), umode);
2678 	if (server_index == primary_server)
2679 	  malloc_strcpy(&send_umode, umode);
2680      }
2681 }
2682 
2683 /*
2684  * is the server ready for login?
2685  */
2686 int
is_ready_for_login(server_index)2687 is_ready_for_login(server_index)
2688    int server_index;
2689 {
2690    if (server_index >= 0 && server_index < number_of_servers
2691        && (server_list[server_index].flags & SRV_CONNECTED))
2692      return 1;
2693    return 0;
2694 }
2695