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(¤t));
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