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