1 /*
2 * Copyright Colten Edwards (c) 1996
3 */
4 #include "irc.h"
5 static char cvsrevision[] = "$Id: misc.c 511 2014-10-21 12:21:24Z keaston $";
6 CVS_REVISION(misc_c)
7
8 #ifdef HAVE_LIBIPHLPAPI
9 #define WIN32_LEAN_AND_MEAN
10 #include <windows.h>
11 #include <iphlpapi.h>
12 #endif
13
14 #include <stdio.h>
15 #include <ctype.h>
16
17 #include <sys/types.h>
18 #include <sys/stat.h>
19 #include <signal.h>
20
21 #include <sys/time.h>
22 #include <sys/types.h>
23 #ifndef __OPENNT
24 #include <sys/resource.h>
25 #endif
26 #include <unistd.h>
27
28 #if defined(sparc) && defined(sun4c)
29 #include <sys/rusage.h>
30 #endif
31
32 #include "struct.h"
33
34 #include "server.h"
35 #include "dcc.h"
36 #include "commands.h"
37 #include "encrypt.h"
38 #include "vars.h"
39 #include "ircaux.h"
40 #include "lastlog.h"
41 #include "window.h"
42 #include "screen.h"
43 #include "who.h"
44 #include "hook.h"
45 #include "input.h"
46 #include "ignore.h"
47 #include "keys.h"
48 #include "names.h"
49 #include "alias.h"
50 #include "history.h"
51 #include "funny.h"
52 #include "ctcp.h"
53 #include "output.h"
54 #include "exec.h"
55 #include "notify.h"
56 #include "numbers.h"
57 #include "status.h"
58 #include "list.h"
59 #include "timer.h"
60 #include "userlist.h"
61 #include "misc.h"
62 #include "gui.h"
63 #include "cdns.h"
64 #include "flood.h"
65 #include "parse.h"
66 #include "whowas.h"
67 #include "hash2.h"
68 #include "cset.h"
69 #include "if.h"
70 #define MAIN_SOURCE
71 #include "modval.h"
72
73 #ifdef GUI
74 extern int guiipc[2];
75 extern int newscrollerpos, lastscrollerpos, lastscrollerwindow;
76 #endif
77
78
79 extern int user_count;
80 extern int shit_count;
81 extern int bot_count;
82 extern int in_server_ping;
83
84 int serv_action = 0;
85
86 #ifndef WANT_CHELP
87 int in_chelp = 0;
88 #endif
89
90 LastMsg last_msg[MAX_LAST_MSG+1] = { { NULL } };
91 LastMsg last_dcc[MAX_LAST_MSG+1] = { { NULL } };
92 LastMsg last_notice[MAX_LAST_MSG+1] = { { NULL } };
93 LastMsg last_servermsg[MAX_LAST_MSG+1] = { { NULL } };
94 LastMsg last_sent_msg[MAX_LAST_MSG+1] = {{ NULL }};
95 LastMsg last_sent_notice[MAX_LAST_MSG+1] = {{ NULL }};
96 LastMsg last_sent_topic[2] = {{ NULL }};
97 LastMsg last_sent_wall[2] = {{ NULL }};
98 LastMsg last_topic[2] = {{ NULL }};
99 LastMsg last_wall[MAX_LAST_MSG+1] = {{ NULL }};
100 LastMsg last_invite_channel[2] = {{ NULL }};
101 LastMsg last_ctcp[2] = {{ NULL }};
102 LastMsg last_ctcp_reply[2] = {{ NULL }};
103 LastMsg last_sent_ctcp[2] = {{ NULL }};
104 LastMsg last_sent_dcc[MAX_LAST_MSG+1] = {{ NULL }};
105
106 extern int in_cparse;
107
108
109 ChannelList *idlechan_list = NULL;
110
111 extern NickTab *tabkey_array, *autoreply_array;
112
113
114 extern Ignore *ignored_nicks;
115
116 #ifdef REVERSE_WHITE_BLACK
117 char *color_str[] = {
118 "[0m","[0;34m","[0;32m","[0;36m","[0;31m","[0;35m","[0;33m","[0;30m",
119 "[1;37m","[1;34m","[1;32m","[1;36m","[1;31m","[1;35m","[1;33m","[1;30m", "[0m",
120 "[0;47m", "[0;41m", "[0;42m","[0;43m", "[0;44m","[0;45m","[0;46m", "[0;40m",
121 "[1;47m", "[1;41m", "[1;42m","[1;43m", "[1;44m","[1;45m","[1;46m", "[1;40m",
122 "[7m", "[1m", "[5m", "[4m"};
123
124 #else
125
126 char *color_str[] = {
127 "[0;30m","[0;34m","[0;32m","[0;36m","[0;31m","[0;35m","[0;33m","[0m",
128 "[1;30m","[1;34m","[1;32m","[1;36m","[1;31m","[1;35m","[1;33m","[1;37m", "[0m",
129 "[0;40m", "[0;41m", "[0;42m","[0;43m", "[0;44m","[0;45m","[0;46m", "[0;47m",
130 "[1;40m", "[1;41m", "[1;42m","[1;43m", "[1;44m","[1;45m","[1;46m", "[1;47m",
131 "[7m", "[1m", "[5m", "[4m"};
132 #endif
133
134
135 va_list VA_NULL = {0,};
136
137 char *awaymsg = NULL;
138
convert_time(time_t ltime)139 char *convert_time (time_t ltime)
140 {
141 unsigned long days = 0,hours = 0,minutes = 0,seconds = 0;
142 static char buffer[40];
143
144
145 *buffer = '\0';
146 seconds = ltime % 60;
147 ltime = (ltime - seconds) / 60;
148 minutes = ltime%60;
149 ltime = (ltime - minutes) / 60;
150 hours = ltime % 24;
151 days = (ltime - hours) / 24;
152 sprintf(buffer, "%2lud %2luh %2lum %2lus", days, hours, minutes, seconds);
153 return(*buffer ? buffer : empty_string);
154 }
155
BUILT_IN_COMMAND(do_uptime)156 BUILT_IN_COMMAND(do_uptime)
157 {
158
159 #ifdef ONLY_STD_CHARS
160 put_it("%s",convert_output_format("%G--[ %WBitchX%g-%wClient%g-%RStatistics %G]------------------------------------------",NULL));
161 put_it("%s",convert_output_format("%G| %CClient Version: %W$0 $1","%s %s", irc_version, internal_version));
162 put_it("%s",convert_output_format("%G| %CClient Running Since %W$0-","%s",my_ctime(start_time)));
163 put_it("%s",convert_output_format("%G| %CClient Uptime: %W$0-","%s",convert_time(now-start_time)));
164 put_it("%s",convert_output_format("%G| %CCurrent UserName: %W$0-","%s", username));
165 put_it("%s",convert_output_format("%G| %CCurrent RealName: %W$0-","%s", realname));
166 put_it("%s",convert_output_format("%G| %CLast Recv Message: %W$0-","%s",last_msg[0].last_msg?last_msg[0].last_msg:"None"));
167 put_it("%s",convert_output_format("%G| %CLast Recv Notice: %W$0-","%s",last_notice[0].last_msg?last_notice[0].last_msg:"None"));
168 put_it("%s",convert_output_format("%G| %CLast Sent Msg: %W$0-","%s",last_sent_msg[0].last_msg?last_sent_msg[0].last_msg:"None"));
169 put_it("%s",convert_output_format("%G| %CLast Sent Notice: %W$0-","%s",last_sent_notice[0].last_msg?last_sent_notice[0].last_msg:"None"));
170 put_it("%s",convert_output_format("%G| %CLast Channel invited to: %R$0-","%s",invite_channel?invite_channel:"None"));
171 put_it("%s",convert_output_format("%G| %cTotal Users on Userlist: %K[%R$0%K]","%d",user_count));
172 put_it("%s",convert_output_format("%G| %cTotal Users on Shitlist: %K[%R$0%K]","%d",shit_count));
173
174 #else
175 put_it("%s",convert_output_format("%G��[ %WBitchX%g�%wClient%g�%RStatistics %G]����---%g�--��%K-%g�����--%G�--��%K-%g�������--- %K--%g -",NULL));
176 put_it("%s",convert_output_format("%G| %CClient Version: %W$0 $1","%s %s", irc_version, internal_version));
177 put_it("%s",convert_output_format("%G� %CClient Running Since %W$0-","%s",my_ctime(start_time)));
178 put_it("%s",convert_output_format("%G| %CClient Uptime: %W$0-","%s",convert_time(now-start_time)));
179 put_it("%s",convert_output_format("%G� %CCurrent UserName: %W$0-","%s", username));
180 put_it("%s",convert_output_format("%G: %CCurrent RealName: %W$0-","%s", realname));
181 put_it("%s",convert_output_format("%G. %CLast Recv Message: %W$0-","%s",last_msg[0].last_msg?last_msg[0].last_msg:"None"));
182 put_it("%s",convert_output_format("%G: %CLast Recv Notice: %W$0-","%s",last_notice[0].last_msg?last_notice[0].last_msg:"None"));
183 put_it("%s",convert_output_format("%G. %CLast Sent Msg: %W$0-","%s",last_sent_msg[0].last_msg?last_sent_msg[0].last_msg:"None"));
184 put_it("%s",convert_output_format("%G: %CLast Sent Notice: %W$0-","%s",last_sent_notice[0].last_msg?last_sent_notice[0].last_msg:"None"));
185 put_it("%s",convert_output_format("%G� %CLast Channel invited to: %R$0-","%s",invite_channel?invite_channel:"None"));
186 put_it("%s",convert_output_format("%G| %cTotal Users on Userlist: %K[%R$0%K]","%d",user_count));
187 put_it("%s",convert_output_format("%G� %cTotal Users on Shitlist: %K[%R$0%K]","%d",shit_count));
188
189 #endif
190 }
191
192 /* extern_write -- controls whether others may write to our terminal or not. */
193 /* This is basically stolen from bsd -- so its under the bsd copyright */
BUILT_IN_COMMAND(extern_write)194 BUILT_IN_COMMAND(extern_write)
195 {
196 char *tty;
197 struct stat sbuf;
198 const int OTHER_WRITE = 020;
199 int on = 0;
200
201 if (!(tty = ttyname(2)))
202 {
203 yell("Error in ttyname()");
204 return;
205 }
206 if (stat(tty, &sbuf) < 0)
207 {
208 yell("Error in stat()");
209 return;
210 }
211 if (!args || !*args)
212 {
213 if (sbuf.st_mode & 020)
214 bitchsay("Mesg is \002On\002");
215 else
216 bitchsay("Mesg is \002Off\002");
217 return;
218 }
219 if (!my_stricmp(args, "ON") || !my_stricmp(args, "YES"))
220 on = 1;
221 else if (!my_stricmp(args, "OFF") || !my_stricmp(args, "NO"))
222 on = 0;
223 else
224 return;
225
226 switch (on)
227 {
228 case 1 :
229 if (chmod(tty, sbuf.st_mode | OTHER_WRITE) < 0)
230 {
231 yell("Sorry, couldnt set your tty's mode");
232 return;
233 }
234 bitchsay("Mesg is \002On\002");
235 break;
236 case 0 :
237 if (chmod(tty, sbuf.st_mode &~ OTHER_WRITE) < 0)
238 {
239 yell("Sorry, couldnt set your tty's mode");
240 return;
241 }
242 bitchsay("Mesg is \002Off\002");
243 break;
244 }
245
246 }
247
248
check_serverlag(void)249 int check_serverlag(void)
250 {
251 int i;
252
253 for (i = 0; i < server_list_size(); i++)
254 {
255 if (is_server_connected(i) && now != get_server_lagtime(i))
256 {
257 set_server_lagtime(i, now);
258 my_send_to_server(i, "PING %s %s", get_server_nickname(i), get_server_itsname(i));
259 in_server_ping++;
260 set_server_lag(i, -1);
261 }
262 }
263
264 return 0;
265 }
266
timer_unban(void * args,char * sub)267 int timer_unban (void *args, char *sub)
268 {
269 char *p = (char *)args;
270 char *channel;
271 ChannelList *chan, *chan2;
272 char *ban;
273 char *serv;
274 int server = from_server;
275
276 serv = next_arg(p, &p);
277 if (my_atol(serv) != server)
278 server = my_atol(serv);
279 if (server < 0 || server > server_list_size() || !is_server_connected(server))
280 server = from_server;
281 channel = next_arg(p, &p);
282 ban = next_arg(p, &p);
283
284 chan2 = get_server_channels(server);
285 if ((chan = (ChannelList *)find_in_list((List **)&chan2, channel, 0)) && ban_is_on_channel(ban, chan))
286 my_send_to_server(server, "MODE %s -b %s", channel, ban);
287 new_free(&serv); new_free(&sub);
288 return 0;
289 }
290
timer_idlekick(void * args,char * sub)291 int timer_idlekick (void *args, char *sub)
292 {
293 char *channel = (char *)args;
294 ChannelList *tmp = NULL;
295 int kick_count = 0;
296 UserList *user = NULL;
297
298
299 if (channel && (tmp = lookup_channel(channel, from_server, CHAN_NOUNLINK)) && tmp->have_op && tmp->max_idle && tmp->check_idle)
300 {
301 NickList *nick;
302 for (nick = next_nicklist(tmp, NULL); nick; nick = next_nicklist(tmp, nick))
303 {
304 if (!my_stricmp(nick->nick, get_server_nickname(from_server)))
305 continue;
306 if ((nick_isop(nick) || nick_isvoice(nick)) && !get_cset_int_var(tmp->csets, KICK_OPS_CSET))
307 continue;
308 if ((user=nick->userlist) && check_channel_match(user->channels, channel))
309 continue;
310 if (now - nick->idle_time >= tmp->max_idle)
311 {
312 if (kick_count <= get_int_var(MAX_IDLEKICKS_VAR))
313 {
314 char *p = NULL;
315 malloc_sprintf(&p, "%s %s*!*%s", channel, nick->nick, nick->host);
316 send_to_server("MODE %s +b %s*!*%s", channel, nick->nick, nick->host);
317 send_to_server("KICK %s %s :\002%s\002: (Idle Channel User)", channel, nick->nick, version);
318 add_timer(0, empty_string, 60 * 1000, 1, timer_unban, m_sprintf("%d %s", from_server, p), NULL, current_window->refnum, "idle-kick");
319 new_free(&p);
320 }
321 else
322 break;
323 kick_count++;
324 }
325 }
326 }
327 if (tmp && tmp->max_idle && tmp->check_idle)
328 add_timer(0, empty_string, get_int_var(IDLE_CHECK_VAR) * 1000, 1, timer_idlekick, channel, NULL, current_window->refnum, "idle-kick");
329 else
330 new_free(&channel);
331 new_free(&sub);
332 return 0;
333 }
334
BUILT_IN_COMMAND(addidle)335 BUILT_IN_COMMAND(addidle)
336 {
337 time_t default_idle = 10 * 60;
338 char *channel = NULL, *p;
339 time_t seconds = 0;
340 ChannelList *tmp, *new = NULL;
341
342
343 if ((p = next_arg(args, &args)))
344 {
345 malloc_strcpy(&channel, make_channel(p));
346 if (!channel)
347 return;
348 if (args && *args)
349 seconds = atol(args);
350
351 if (seconds < default_idle)
352 seconds = default_idle;
353
354 if (!(new = (ChannelList *)find_in_list((List **)&idlechan_list, channel, 0)))
355 {
356 new = (ChannelList *)new_malloc(sizeof(ChannelList));
357 malloc_strcpy(&new->channel, channel);
358 add_to_list((List **)&idlechan_list, (List *)new);
359 }
360 new->max_idle = seconds;
361 new->check_idle = (my_strnicmp(command, "UN", 2) == 0) ? 0: 1;
362
363 if (!new->check_idle)
364 {
365 bitchsay("Idle checking turned %s for %s",on_off(new->check_idle), channel);
366 if ((tmp = lookup_channel(channel, from_server, CHAN_NOUNLINK)))
367 tmp->check_idle = tmp->max_idle = 0;
368 new->max_idle = 0;
369 }
370 else
371 {
372 if ((tmp = lookup_channel(channel, from_server, CHAN_NOUNLINK)))
373 {
374 if (new && new->check_idle)
375 {
376 tmp->max_idle = new->max_idle;
377 tmp->check_idle = new->check_idle;
378 add_timer(0, empty_string, get_int_var(IDLE_CHECK_VAR) * 1000, 1, timer_idlekick, channel, NULL, current_window->refnum, "idle-check");
379 bitchsay("Idle checking turned %s for %s %d mins",on_off(tmp->check_idle), channel, (int)(tmp->max_idle/60));
380 }
381 }
382 }
383 new_free(&channel);
384 }
385 }
386
BUILT_IN_COMMAND(showidle)387 BUILT_IN_COMMAND(showidle)
388 {
389 ChannelList *tmp;
390 char *channel = NULL;
391 int count = 0;
392 NickList *nick, *ntmp;
393 time_t ltime;
394 int server;
395 int sorted = 0;
396 while (args && *args)
397 {
398 if (!args || !*args)
399 break;
400 if ((*args == '-') && !my_strnicmp(args, "-sort", 3))
401 {
402 next_arg(args, &args);
403 sorted = NICKSORT_NONE;
404 }
405 else if (!my_strnicmp(args, "nick", 3) && sorted)
406 {
407 next_arg(args, &args);
408 sorted = NICKSORT_NICK;
409 }
410 else if (!my_strnicmp(args, "host", 3) && sorted)
411 {
412 next_arg(args, &args);
413 sorted = NICKSORT_HOST;
414 }
415 else if (!my_strnicmp(args, "time", 3) && sorted)
416 {
417 next_arg(args, &args);
418 sorted = NICKSORT_TIME;
419 }
420 else if (!my_strnicmp(args, "ip", 2) && sorted)
421 {
422 next_arg(args, &args);
423 sorted = NICKSORT_IP;
424 }
425 else
426 channel = next_arg(args, &args);
427 }
428 if (!(tmp = prepare_command(&server, channel, NO_OP)))
429 return;
430
431 ntmp = sorted_nicklist(tmp, sorted);
432 for (nick = ntmp; nick; nick = nick->next)
433 {
434 if (!count && do_hook(SHOWIDLE_HEADER_LIST, "%s %lu", tmp->channel, (unsigned long)tmp->max_idle))
435 put_it("%s", convert_output_format("$G %W$a%n: Idle check for %W$0%n Max Idle Time %K[%W$1- %K]", "%s %s", tmp->channel, convert_time(tmp->max_idle)));
436 ltime = now - nick->idle_time;
437 #ifdef WANT_USERLIST
438 if (do_hook(SHOWIDLE_LIST, "%s %s %d %lu", nick->nick, nick->host, find_user_level(nick->nick, nick->host, tmp->channel), (unsigned long)ltime))
439 #else
440 if (do_hook(SHOWIDLE_LIST, "%s %s %d %lu", nick->nick, nick->host, 0, (unsigned long)ltime))
441 #endif
442 put_it("%s", convert_output_format("$[20]0 Idle%W: %K[%n$1- %K]", "%s %s", nick->nick, convert_time(ltime)));
443 count++;
444 }
445 if (count)
446 do_hook(SHOWIDLE_FOOTER_LIST, "%s", "End of idlelist");
447 clear_sorted_nicklist(&ntmp);
448 }
449
BUILT_IN_COMMAND(kickidle)450 BUILT_IN_COMMAND(kickidle)
451 {
452 char *channel = NULL;
453 ChannelList *tmp;
454 int kick_count = 0;
455 int server = from_server;
456
457
458 if (args && *args)
459 channel = next_arg(args, &args);
460
461 if ((tmp = prepare_command(&server, channel, NEED_OP)) && tmp->max_idle)
462 {
463 NickList *nick;
464 for (nick = next_nicklist(tmp, NULL); nick; nick = next_nicklist(tmp, nick))
465 {
466 if (!my_stricmp(nick->nick, get_server_nickname(from_server)))
467 continue;
468 if (nick->userlist && check_channel_match(nick->userlist->channels, tmp->channel))
469 continue;
470 if (nick_isop(nick))
471 continue;
472 if (now - nick->idle_time >= tmp->max_idle)
473 {
474 if (kick_count <= get_int_var(MAX_IDLEKICKS_VAR))
475 my_send_to_server(server, "KICK %s %s :\002%s\002: (Idle Channel User)", tmp->channel, nick->nick, version);
476 else
477 bitchsay(" found idle user %-12s channel %s", nick->nick, tmp->channel);
478 kick_count++;
479 }
480 }
481 }
482 }
483
save_idle(FILE * output)484 void save_idle(FILE *output)
485 {
486 ChannelList *chan;
487 int count = 0;
488
489
490 if (!output)
491 return;
492 if (idlechan_list)
493 {
494 fprintf(output, "# %s Idle Channel list\n", version);
495 for (chan = idlechan_list; chan; chan = chan->next)
496 {
497 if (chan->max_idle)
498 {
499 fprintf(output, "ADDIDLE %s %d\n", chan->channel, (int)chan->max_idle);
500 count++;
501 }
502 }
503 }
504 if (count && do_hook(SAVEFILE_LIST, "Idle %d", count))
505 bitchsay("Saved %d Idle channels", count);
506 }
507
BUILT_IN_COMMAND(channel_stats)508 BUILT_IN_COMMAND(channel_stats)
509 {
510 ChannelList *new = NULL;
511 char *channel = NULL;
512 WhowasChanList *new1 = NULL;
513 int numircops = 0;
514 int usershere = 0;
515 int usersaway = 0;
516 int chanops = 0;
517 int chanunop = 0;
518 char *ircops = NULL;
519 int server = -1;
520 int max_hops = 0;
521
522 NickList *l;
523 unsigned long nick_mem = 0,
524 ban_mem = 0;
525 BanList *b;
526
527
528
529
530 if (args && *args)
531 {
532 channel = next_arg(args, &args);
533 if (my_strnicmp(channel, "-ALL", strlen(channel)))
534 {
535 if (!(channel = make_channel(channel)))
536 return;
537 if (!(new = prepare_command(&server, channel, PC_SILENT)))
538 if ((channel && !(new1 = check_whowas_chan_buffer(channel, -1, 0))))
539 return;
540 }
541 else
542 {
543
544 int stats_ops= 0, stats_dops = 0, stats_bans = 0, stats_unbans = 0;
545 int stats_topics = 0, stats_kicks = 0, stats_pubs = 0, stats_parts = 0;
546 int stats_signoffs = 0, stats_joins = 0;
547 int total_nicks = 0, max_nicks = 0, total_bans = 0, max_bans = 0;
548 int stats_sops = 0, stats_sdops = 0, stats_sbans = 0, stats_sunbans = 0;
549
550 NickList *l;
551 BanList *b;
552 unsigned long chan_mem = 0;
553 channel = NULL;
554
555 if (from_server != -1)
556 {
557 for (new = get_server_channels(from_server); new; new = new->next)
558 {
559 if (!channel)
560 malloc_strcpy(&channel, new->channel);
561 else
562 {
563 malloc_strcat(&channel, ",");
564 malloc_strcat(&channel, new->channel);
565 }
566 for (l = next_nicklist(new, NULL); l; l = next_nicklist(new, l))
567 {
568 if (nick_isaway(l))
569 usersaway++;
570 else
571 usershere++;
572 if (nick_isircop(l))
573 {
574 numircops++;
575 malloc_strcat(&ircops, " (");
576 malloc_strcat(&ircops, l->nick);
577 malloc_strcat(&ircops, ")");
578 }
579 if (nick_isop(l))
580 chanops++;
581 else
582 chanunop++;
583 nick_mem += sizeof(NickList);
584 if (l->serverhops > max_hops)
585 max_hops = l->serverhops;
586 }
587 for (b = new->bans; b; b = b->next)
588 ban_mem += sizeof(BanList);
589 chan_mem += sizeof(ChannelList);
590 stats_ops += new->stats_ops;
591 stats_dops += new->stats_dops;
592 stats_bans += new->stats_bans;
593 stats_unbans += new->stats_unbans;
594 stats_topics += new->stats_topics;
595 stats_kicks += new->stats_kicks;
596 stats_pubs += new->stats_pubs;
597 stats_parts += new->stats_parts;
598 stats_signoffs += new->stats_signoffs;
599 stats_joins += new->stats_joins;
600
601 total_nicks += new->totalnicks;
602 max_nicks += new->maxnicks;
603 total_bans += new->totalbans;
604 max_bans += new->maxbans;
605 stats_sops += new->stats_sops;
606 stats_sdops += new->stats_sdops;
607 stats_sbans += new->stats_sbans;
608 stats_sunbans += new->stats_sunbans;
609 }
610 }
611 if (!ircops)
612 malloc_strcat(&ircops, empty_string);
613 if (do_hook(CHANNEL_STATS_LIST, "%s %s %s %lu %lu %lu %lu %u %u %u %u %u %u %u %u %u %u %u %u %u %u %u %u %u %u %u %u %u %u %u %d %s",
614 channel, empty_string, empty_string,
615 nick_mem+chan_mem+ban_mem, nick_mem,
616 (unsigned long)sizeof(ChannelList),ban_mem,
617 stats_ops, stats_dops, stats_bans, stats_unbans,
618 stats_topics, stats_kicks, stats_pubs, stats_parts,
619 stats_signoffs, stats_joins, total_bans, max_bans,
620 stats_sops, stats_sdops,stats_sbans, stats_sunbans,
621 usershere, usersaway, chanops, chanunop,total_nicks,max_nicks,
622 numircops, max_hops, ircops))
623 {
624 put_it("%s", convert_output_format("$G %CInformation for channels %K: %W$0", "%s", channel));
625 put_it("%s", convert_output_format(" MEM usage%K:%w Total%K:%w %c$0 bytes %K[%cNicks $1 b Chan $2 b Bans $3 b%K]", "%d %d %d %d", (int)(nick_mem+chan_mem+ban_mem), (int)nick_mem, (int)sizeof(ChannelList), (int)ban_mem));
626 put_it("%s", convert_output_format("Ops %K[%W$[-5]0%K]%w De-Ops %K[%W$[-5]1%K]%w Bans %K[%W$[-5]2%K]%w Unbans %K[%W$[-5]3%K]%w", "%u %u %u %u", stats_ops, stats_dops, stats_bans, stats_unbans));
627 put_it("%s", convert_output_format("Topics %K[%W$[-5]0%K]%w Kicks %K[%W$[-5]1%K]%w Publics %K[%W$[-5]2%K]%w Parts %K[%W$[-5]3%K]%w", "%u %u %u %u", stats_topics, stats_kicks, stats_pubs, stats_parts));
628 put_it("%s", convert_output_format("Signoffs %C[%W$[-5]0%K]%w Joins %K[%W$[-5]1%K]%w TotalBans %K[%W$[-5]2%K]%w MaxBans %K[%W$[-5]3%K]%w", "%u %u %u %u", stats_signoffs, stats_joins, total_bans, max_bans));
629 put_it("%s", convert_output_format("ServOps %K[%W$[-5]0%K]%w ServDeop %K[%W$[-5]1%K]%w ServBans %K[%W$[-5]2%K]%w ServUB %K[%W$[-5]3%K]%w", "%u %u %u %u", stats_sops, stats_sdops,stats_sbans, stats_sunbans));
630 put_it("%s", convert_output_format("Users Here %K[%W$[-5]0%K]%w Users Away %K[%W$[-5]1%K]%w Opped %K[%W$[-5]2%K]%w Unopped %K[%W$[-5]3%K]%w", "%u %u %u %u", usershere, usersaway, chanops, chanunop));
631 put_it("%s", convert_output_format("TotalNicks %K[%W$[-5]0%K]%w MaxNicks %K[%W$[-5]1%K]%w ServerHops %K[%W$[-5]2%K]%w", "%d %d %d", total_nicks,max_nicks, max_hops));
632 put_it("%s", convert_output_format("IRCops %K[%W$[3]0%K]%w$1-", "%d %s", numircops, ircops));
633 }
634 new_free(&ircops);
635 new_free(&channel);
636 return;
637 }
638 }
639 else
640 {
641 if (!(new = prepare_command(&server, channel, PC_SILENT)))
642 if ((channel && !(new1 = check_whowas_chan_buffer(channel, -1, 0))))
643 return;
644 }
645
646 if (!new && new1)
647 new = new1->channellist;
648 if (!new)
649 {
650 bitchsay("Try joining a channel first");
651 return;
652 }
653 if (new)
654 {
655 for (l = next_nicklist(new, NULL); l; l = next_nicklist(new, l))
656 {
657 nick_mem += sizeof(NickList);
658 if (nick_isaway(l))
659 usersaway++;
660 else
661 usershere++;
662 if (nick_isircop(l))
663 {
664 numircops++;
665 malloc_strcat(&ircops, " (");
666 malloc_strcat(&ircops, l->nick);
667 malloc_strcat(&ircops, ")");
668 }
669 if (nick_isop(l))
670 chanops++;
671 else
672 chanunop++;
673 if (l->serverhops > max_hops)
674 max_hops = l->serverhops;
675 }
676 for (b = new->bans; b; b = b->next)
677 ban_mem += sizeof(BanList);
678 }
679 if (!ircops)
680 malloc_strcat(&ircops, empty_string);
681 if (do_hook(CHANNEL_STATS_LIST, "%s %s %s %ld %ld %ld %ld %u %u %u %u %u %u %u %u %u %u %u %u %u %u %u %u %u %u %u %u %u %u %u %d %s",
682 new->channel, my_ctime(new->channel_create.tv_sec), convert_time(now-new->join_time.tv_sec),
683 nick_mem+sizeof(ChannelList)+ban_mem, nick_mem,
684 (unsigned long)sizeof(ChannelList),ban_mem,
685 new->stats_ops, new->stats_dops, new->stats_bans, new->stats_unbans,
686 new->stats_topics, new->stats_kicks, new->stats_pubs, new->stats_parts,
687 new->stats_signoffs, new->stats_joins, new->totalbans, new->maxbans,
688 new->stats_sops, new->stats_sdops,new->stats_sbans, new->stats_sunbans,
689 usershere, usersaway, chanops, chanunop,new->totalnicks,new->maxnicks,
690 numircops, max_hops, ircops))
691 {
692 put_it("%s", convert_output_format("$G %CInformation for channel %K: %W$0", "%s", new->channel));
693 put_it("%s", convert_output_format("$G %CChannel created %K: %W$0 $1 $2 $3%n in memory %W$4-", "%s %s", convert_time(now-new->channel_create.tv_sec), my_ctime(new->join_time.tv_sec)));
694
695 put_it("%s", convert_output_format(" MEM usage%K:%w Total%K:%w %c$0 bytes %K[%cNicks $1 b Chan $2 b Bans $3 b%K]", "%d %d %d %d", (int)(nick_mem+sizeof(ChannelList)+ban_mem), (int)nick_mem, (int)sizeof(ChannelList), (int)ban_mem));
696 put_it("%s", convert_output_format("Ops %K[%W$[-5]0%K]%w De-Ops %K[%W$[-5]1%K]%w Bans %K[%W$[-5]2%K]%w Unbans %K[%W$[-5]3%K]%w", "%u %u %u %u", new->stats_ops, new->stats_dops, new->stats_bans, new->stats_unbans));
697 put_it("%s", convert_output_format("Topics %K[%W$[-5]0%K]%w Kicks %K[%W$[-5]1%K]%w Publics %K[%W$[-5]2%K]%w Parts %K[%W$[-5]3%K]%w", "%u %u %u %u", new->stats_topics, new->stats_kicks, new->stats_pubs, new->stats_parts));
698 put_it("%s", convert_output_format("Signoffs %K[%W$[-5]0%K]%w Joins %K[%W$[-5]1%K]%w TotalBans %K[%W$[-5]2%K]%w MaxBans %K[%W$[-5]3%K]%w", "%u %u %u %u", new->stats_signoffs, new->stats_joins, new->totalbans, new->maxbans));
699 put_it("%s", convert_output_format("ServOps %K[%W$[-5]0%K]%w ServDeop %K[%W$[-5]1%K]%w ServBans %K[%W$[-5]2%K]%w ServUB %K[%W$[-5]3%K]%w", "%u %u %u %u", new->stats_sops, new->stats_sdops,new->stats_sbans, new->stats_sunbans));
700 put_it("%s", convert_output_format("Users Here %K[%W$[-5]0%K]%w Users Away %K[%W$[-5]1%K]%w Opped %K[%W$[-5]2%K]%w Unopped %K[%W$[-5]3%K]%w", "%u %u %u %u", usershere, usersaway, chanops, chanunop));
701 put_it("%s", convert_output_format("TotalNicks %K[%W$[-5]0%K]%w MaxNicks %K[%W$[-5]1%K]%w ServerHops %K[%W$[-5]2%K]%w", "%d %d %d", new->totalnicks,new->maxnicks, max_hops));
702 put_it("%s", convert_output_format("IRCops %K[%W$[3]0%K]%w$1-", "%d %s", numircops, ircops));
703
704 put_it("%s", convert_output_format(" %CThere is %R$0%C limit and limit checking is %R$1-", "%s %s", new->limit ? ltoa(new->limit): "no", new->tog_limit?"Enabled":"Disabled"));
705 put_it("%s", convert_output_format(" %CIdle user check is %K[%R$0-%K]", "%s", new->check_idle?"Enabled":"Disabled"));
706 /*put_it("%s", convert_output_format("$G End of channel stats for $0", "%s", new->channel));*/
707 /* wtf is do_scan in the channel struct */
708 }
709 new_free(&ircops);
710
711 }
712
update_stats(int what,NickList * nick,ChannelList * chan,int splitter)713 void update_stats(int what, NickList *nick, ChannelList *chan, int splitter)
714 {
715 time_t this_time = now;
716 int t = 0;
717
718
719 if (!chan || !chan->channel)
720 return;
721
722 switch (what)
723 {
724 case KICKLIST:
725 {
726 chan->stats_kicks++;
727 chan->totalnicks--;
728 if (nick) nick->stat_kicks++;
729 break;
730 }
731
732 case LEAVELIST:
733 {
734 chan->stats_parts++;
735 chan->totalnicks--;
736 break;
737 }
738 case JOINLIST:
739 {
740 chan->stats_joins++;
741 chan->totalnicks++;
742 if (chan->totalnicks > chan->maxnicks)
743 {
744 chan->maxnicks = chan->totalnicks;
745 chan->maxnickstime = this_time;
746 }
747 if (!splitter)
748 {
749 if (chan->have_op && is_other_flood(chan, nick, JOIN_FLOOD, &t))
750 {
751 if (get_cset_int_var(chan->csets, JOINFLOOD_CSET) && get_cset_int_var(chan->csets, KICK_ON_JOINFLOOD_CSET) && !nick->kickcount++)
752 {
753 char *t1, *host, *banstr;
754 t1 = LOCAL_COPY(nick->host);
755 host = strchr(t1, '@');
756 *host++ = 0;
757 banstr = ban_it(nick->nick, t1, host, nick->ip);
758 send_to_server("MODE %s -o+b %s %s", chan->channel, nick->nick, banstr);
759 send_to_server("KICK %s %s :\002Join flood\002 (%d joins in %dsecs of %dsecs)", chan->channel, nick->nick, get_cset_int_var(chan->csets, KICK_ON_JOINFLOOD_CSET)/*chan->set_kick_on_joinflood*/, t, get_cset_int_var(chan->csets, JOINFLOOD_TIME_CSET));
760 if (get_int_var(AUTO_UNBAN_VAR))
761 add_timer(0, empty_string, get_int_var(AUTO_UNBAN_VAR) * 1000, 1, timer_unban, m_sprintf("%d %s %s", from_server, chan->channel, banstr), NULL, current_window->refnum, "join-flood");
762 }
763 }
764 }
765 break;
766 }
767 case CHANNELSIGNOFFLIST:
768 {
769 chan->stats_signoffs++;
770 chan->totalnicks--;
771 break;
772 }
773 case PUBLICLIST:
774 case PUBLICOTHERLIST:
775 case PUBLICNOTICELIST:
776 case NOTICELIST:
777 {
778 chan->stats_pubs++;
779 if (nick)
780 {
781 nick->stat_pub++;
782 nick->idle_time = this_time;
783 }
784 break;
785 }
786 case TOPICLIST:
787 {
788 chan->stats_topics++;
789 break;
790 }
791 case MODEOPLIST:
792 if (splitter)
793 chan->stats_sops++;
794 else
795 {
796 if (nick) nick->stat_ops++;
797 chan->stats_ops++;
798 }
799 break;
800 case MODEHOPLIST:
801 if (splitter)
802 chan->stats_shops++;
803 else
804 {
805 if (nick) nick->stat_hops++;
806 chan->stats_hops++;
807 }
808 break;
809 case MODEDEHOPLIST:
810 if (splitter)
811 chan->stats_sdehops++;
812 else
813 {
814 if (nick) nick->stat_dhops++;
815 chan->stats_dhops++;
816 }
817 break;
818 case MODEDEOPLIST:
819 if (splitter)
820 chan->stats_sdops++;
821 else
822 {
823 chan->stats_dops++;
824 if (nick) nick->stat_dops++;
825 }
826
827 if (chan->have_op && is_other_flood(chan, nick, DEOP_FLOOD, &t))
828 {
829 if (get_cset_int_var(chan->csets, DEOP_ON_DEOPFLOOD_CSET) < get_cset_int_var(chan->csets, KICK_ON_DEOPFLOOD_CSET))
830 send_to_server("MODE %s -o %s", chan->channel, nick->nick);
831 else if (!nick->kickcount++)
832 send_to_server("KICK %s %s :\002De-op flood\002 (%d de-ops in %dsecs of %dsecs)", chan->channel, nick->nick, get_cset_int_var(chan->csets, KICK_ON_DEOPFLOOD_CSET), t, get_cset_int_var(chan->csets, DEOPFLOOD_TIME_CSET));
833 }
834 break;
835 case MODEBANLIST:
836 if (splitter)
837 chan->stats_sbans++;
838 else
839 {
840 if (nick) nick->stat_bans++;
841 chan->stats_bans++;
842 }
843 chan->totalbans++;
844 if (chan->stats_bans > chan->maxbans)
845 {
846 chan->maxbans = chan->stats_bans;
847 chan->maxbanstime = this_time;
848 }
849 break;
850 case MODEUNBANLIST:
851 if (splitter)
852 chan->stats_sunbans++;
853 else
854 {
855 if (nick) nick->stat_unbans++;
856 chan->stats_unbans++;
857 }
858 if (chan->totalbans) chan->totalbans--;
859 break;
860 default:
861 break;
862 }
863 }
864
clear_server_flags(char * userhost)865 char *clear_server_flags (char *userhost)
866 {
867 register char *uh = userhost;
868 while(uh && (*uh == '~' || *uh == '#' || *uh == '+' || *uh == '-' || *uh == '=' || *uh == '^'))
869 uh++;
870 return uh;
871 }
872
873
874 #ifndef BITCHX_LITE
875
876 static char newline1[BIG_BUFFER_SIZE+1];
877 /*
878 * (max server send) and max mirc color change is 256
879 * so 256 * 8 should give us a safety margin for hackers.
880 * BIG_BUFFER is 1024 * 3 is 3072 whereas 256*8 is 2048
881 */
882
883
884 #if 0
885 char *mircansi(unsigned char *line)
886 {
887 /* mconv v1.00 (c) copyright 1996 Ananda, all rights reserved. */
888 /* ----------------------------------------------------------- */
889 /* mIRC->ansi color code convertor: 12.26.96 */
890 /* map of mIRC color values to ansi color codes */
891 /* format: ansi fg color ansi bg color */
892 /* modified Colten Edwards */
893 struct {
894 char *fg, *bg;
895 } codes[16] = {
896
897 { "[1;37m", "[47m" }, /* white */
898 { "[0;30m", "[40m" }, /* black (grey for us) */
899 { "[0;34m", "[44m" }, /* blue */
900 { "[0;32m", "[42m" }, /* green */
901 { "[0;31m", "[41m" }, /* red */
902 { "[0;33m", "[43m" }, /* brown */
903
904 { "[0;35m", "[45m" }, /* magenta */
905 { "[1;31m", "[41m" }, /* bright red */
906 { "[1;33m", "[43m" }, /* yellow */
907
908 { "[1;32m", "[42m" }, /* bright green */
909 { "[0;36m", "[46m" }, /* cyan */
910 { "[1;36m", "[46m" }, /* bright cyan */
911 { "[1;34m", "[44m" }, /* bright blue */
912 { "[1;35m", "[45m" }, /* bright magenta */
913 { "[1;30m", "[40m" }, /* dark grey */
914 { "[0;37m", "[47m" } /* grey */
915 };
916 register unsigned char *sptr = line, *dptr = newline1;
917 short code;
918
919 if (!*line)
920 return empty_string;
921 *newline1 = 0;
922 while (*sptr) {
923 if (*sptr == '' && isdigit(sptr[1]))
924 {
925 sptr++;
926 code = atoi(sptr);
927 if (code > 15 || code <= 0)
928 continue;
929 while (isdigit(*sptr))
930 sptr++;
931 strcpy(dptr, codes[code].fg);
932 while (*dptr) dptr++;
933 if (*sptr == ',')
934 {
935 sptr++;
936 code = atoi(sptr);
937 if (code >= 0 && code <= 15)
938 {
939 strcpy(dptr, codes[code].bg);
940 while (*dptr) dptr++;
941 }
942 while (isdigit(*sptr))
943 sptr++;
944 }
945 }
946 else if (*sptr == '')
947 {
948 strcpy(dptr, "[0m");
949 while(*dptr) dptr++;
950 sptr++;
951 }
952 else *dptr++ = *sptr++;
953 }
954 *dptr = 0;
955 return (char *)newline1;
956 }
957 #else
mircansi(const char * line)958 char *mircansi(const char *line)
959 {
960 /* mconv v1.00 (c) copyright 1996 Ananda, all rights reserved. */
961 /* ----------------------------------------------------------- */
962 /* mIRC->ansi color code convertor: 12.26.96 */
963 /* map of mIRC color values to ansi color codes */
964 /* format: ansi fg color ansi bg color */
965 /* modified Colten Edwards */
966 static const struct {
967 const char *fg, *bg;
968 } codes[16] = {
969 { "\x1b[1;37m", "\x1b[47m" }, /* white */
970 { "\x1b[0;30m", "\x1b[40m" }, /* black (grey for us) */
971 { "\x1b[0;34m", "\x1b[44m" }, /* blue */
972 { "\x1b[0;32m", "\x1b[42m" }, /* green */
973 { "\x1b[0;31m", "\x1b[41m" }, /* red */
974 { "\x1b[0;33m", "\x1b[43m" }, /* brown */
975 { "\x1b[0;35m", "\x1b[45m" }, /* magenta */
976 { "\x1b[1;31m", "\x1b[41m" }, /* bright red */
977 { "\x1b[1;33m", "\x1b[43m" }, /* yellow */
978 { "\x1b[1;32m", "\x1b[42m" }, /* bright green */
979 { "\x1b[0;36m", "\x1b[46m" }, /* cyan */
980 { "\x1b[1;36m", "\x1b[46m" }, /* bright cyan */
981 { "\x1b[1;34m", "\x1b[44m" }, /* bright blue */
982 { "\x1b[1;35m", "\x1b[45m" }, /* bright magenta */
983 { "\x1b[1;30m", "\x1b[40m" }, /* dark grey */
984 { "\x1b[0;37m", "\x1b[47m" } /* grey */
985 };
986
987 const char *sptr = line;
988 char *dptr = newline1;
989 unsigned code;
990
991 if (!*line)
992 return empty_string;
993
994 while (*sptr)
995 {
996 if (*sptr == '\x03')
997 {
998 sptr++;
999
1000 if (isdigit((unsigned char)*sptr))
1001 {
1002 /* ^C followed by digit*/
1003 code = *sptr - '0';
1004 sptr++;
1005
1006 if (isdigit((unsigned char)*sptr)) {
1007 code = code * 10 + *sptr - '0';
1008 sptr++;
1009 }
1010
1011 code = code % 16;
1012 strcpy(dptr, codes[code].fg);
1013 while (*dptr)
1014 dptr++;
1015
1016 /* Do not consume , if not followed by digit */
1017 if (sptr[0] == ',' && isdigit((unsigned char)sptr[1]))
1018 {
1019 code = sptr[1] - '0';
1020 sptr += 2;
1021
1022 if (isdigit ((unsigned char)*sptr)) {
1023 code = code * 10 + *sptr - '0';
1024 sptr++;
1025 }
1026
1027 code = code % 16;
1028 strcpy(dptr, codes[code].bg);
1029 while (*dptr)
1030 dptr++;
1031 }
1032 }
1033 else
1034 {
1035 /* ^C not followed by digit - assume end of color */
1036 strcpy(dptr, "\x1b[0m");
1037 while (*dptr)
1038 dptr++;
1039 }
1040 }
1041 else
1042 *dptr++ = *sptr++;
1043 }
1044 *dptr = 0;
1045
1046 return newline1;
1047 }
1048 #endif
1049
1050 /* Borrowed with permission from FLiER */
stripansicodes(const char * line)1051 char *stripansicodes(const char *line)
1052 {
1053 const char *tstr = line;
1054 char *nstr = newline1;
1055 int gotansi = 0;
1056
1057 while (*tstr)
1058 {
1059 /* Note that we use '\x9b' here, rather than 0x9b, because the
1060 * former will have the correct value whether or not char is
1061 * signed.
1062 */
1063 if (*tstr == '\x1b' || *tstr == '\x9b')
1064 gotansi = 1;
1065 if (gotansi && isalpha((unsigned char)*tstr))
1066 gotansi = 0;
1067 else if (!gotansi)
1068 {
1069 *nstr = *tstr;
1070 nstr++;
1071 }
1072 tstr++;
1073 }
1074 *nstr = 0;
1075 return newline1;
1076 }
1077 #else
stripansicodes(const char * line)1078 char *stripansicodes(const char *line)
1079 {
1080 return line;
1081 }
mircansi(unsigned char * line)1082 char *mircansi(unsigned char *line)
1083 {
1084 return line;
1085 }
1086 #endif
1087
stripansi(unsigned char * line)1088 char *stripansi(unsigned char *line)
1089 {
1090 register unsigned char *cp;
1091 unsigned char *newline;
1092 newline = m_strdup(line);
1093 for (cp = newline; *cp; cp++)
1094 if ((*cp < 31 && *cp > 13))
1095 if (*cp != 1 && *cp != 15 && *cp !=22 && *cp != 0x9b)
1096 *cp = (*cp & 127) | 64;
1097 return (char *)newline;
1098 }
1099
1100
check_split(char * nick,char * reason)1101 int check_split(char *nick, char *reason)
1102 {
1103 char *bogus = get_string_var(FAKE_SPLIT_PATS_VAR);
1104 char *Reason;
1105
1106 Reason = LOCAL_COPY(reason);
1107 if (word_count(Reason) > 3)
1108 goto fail_split;
1109 if (wild_match("%.% %.%", Reason) && !strstr(Reason, "))") )
1110 {
1111 char *host1 = next_arg(Reason, &Reason);
1112 char *host2 = next_arg(Reason, &Reason);
1113 char *x = NULL;
1114
1115 if (!my_stricmp(host1, host2))
1116 goto fail_split;
1117 if (wild_match(host1, "*..*") || wild_match(host2, "*..*"))
1118 goto fail_split;
1119 if ((x = strrchr(host1, '.')))
1120 x++;
1121 if (!x || strlen(x) < 2 || strlen(x) > 3)
1122 goto fail_split;
1123 if ((x = strrchr(host2, '.')))
1124 x++;
1125 if (!x || strlen(x) < 2 || strlen(x) > 3)
1126 goto fail_split;
1127
1128 if (bogus)
1129 {
1130 char *copy = NULL;
1131 char *b_check;
1132 copy = LOCAL_COPY(bogus);
1133 while((b_check = next_arg(copy, ©)))
1134 {
1135 if (wild_match(b_check, host1) || wild_match(b_check, host2))
1136 goto fail_split;
1137 }
1138 }
1139 return 1;
1140 }
1141 fail_split:
1142 return 0;
1143 }
1144
clear_array(NickTab ** tmp,char * nick)1145 void clear_array(NickTab **tmp, char *nick)
1146 {
1147 NickTab *t, *q;
1148
1149 if (nick)
1150 {
1151 if ((t = (NickTab *)remove_from_list((List **)tmp, nick)))
1152 {
1153 new_free(&t->nick);
1154 new_free(&t->type);
1155 new_free((char **)&t);
1156 }
1157 return;
1158 }
1159 for (t = *tmp; t; )
1160 {
1161 q = t->next;
1162 new_free(&t->nick);
1163 new_free(&t->type);
1164 new_free((char **)&t);
1165 t = q;
1166 }
1167 *tmp = NULL;
1168 }
1169
1170
BUILT_IN_COMMAND(clear_tab)1171 BUILT_IN_COMMAND(clear_tab)
1172 {
1173 NickTab **tmp = &tabkey_array;
1174 char *nick = NULL;
1175 if (command && *command && !my_stricmp(command, "CLEARAUTO"))
1176 tmp = &autoreply_array;
1177 if (args && *args)
1178 {
1179 while ((nick = next_arg(args, &args)))
1180 clear_array(tmp, nick);
1181 return;
1182 }
1183 clear_array(tmp, nick);
1184 }
1185
BX_userage(char * command,char * use)1186 void BX_userage(char *command, char *use)
1187 {
1188 if (command)
1189 {
1190 if (do_hook(USAGE_LIST, "%s %s", command, use ? use : "No Help Available for this command"))
1191 put_it("%s", convert_output_format(fget_string_var(FORMAT_USAGE_FSET), "%s %s", command, convert_output_format(use ? use : "%WNo Help available for this command", NULL, NULL)));
1192 }
1193 else
1194 put_it("Please return the command you just typed to #bitchx on efnet");
1195 }
1196
BX_random_str(int min,int max)1197 char *BX_random_str(int min, int max)
1198 {
1199 int i, ii;
1200 static char str[IRCD_BUFFER_SIZE/4+1];
1201
1202 while ((i = getrandom(MIN(min, max), MAX(min, max))) > IRCD_BUFFER_SIZE/4)
1203 ;
1204 for (ii = 0; ii < i; ii++)
1205 str[ii] = (char) getrandom(97, 122);
1206 str[ii] = '\0';
1207 return str;
1208 }
1209
1210
check_auto_away(time_t idlet)1211 void check_auto_away(time_t idlet)
1212 {
1213 int i;
1214 char *msg = NULL;
1215 int auto_away_time = get_int_var(AUTO_AWAY_TIME_VAR);
1216 int idle_mins = auto_away_time / 60;
1217
1218 if (!auto_away_time || !get_int_var(AUTO_AWAY_VAR) || idlet < auto_away_time)
1219 return;
1220
1221 if (awaymsg)
1222 malloc_sprintf(&msg, "%s: [%d mins]", convert_output_format(awaymsg, NULL), idle_mins);
1223 else
1224 malloc_sprintf(&msg, "Auto-Away after %d mins", idle_mins);
1225
1226 for (i = 0; i < server_list_size(); i++)
1227 if (is_server_connected(i) && !get_server_away(i))
1228 set_server_away(i, msg, 0);
1229
1230 update_all_status(current_window, NULL, 0);
1231 new_free(&msg);
1232 }
1233
1234 /*char *logfile[] = { "tcl.log", "msg.log", NULL };*/
1235
1236 /* putlog(level,channel_name,format,...); */
putlog(int type,...)1237 void putlog(int type, ...)
1238 {
1239 #ifdef PUBLIC_ACCESS
1240 return;
1241 #else
1242 va_list va;
1243 time_t t;
1244 char *format,
1245 *chname,
1246 *logfilen = NULL,
1247 s[BIG_BUFFER_SIZE+1],
1248 s1[40],
1249 s2[BIG_BUFFER_SIZE+1];
1250 FILE *f;
1251 if (!get_int_var(BOT_LOG_VAR))
1252 return;
1253 if (!(logfilen = get_string_var(BOT_LOGFILE_VAR)))
1254 return;
1255
1256 va_start(va, type);
1257 t = now;
1258 strftime(s1, 30, "%I:%M%p", localtime(&t));
1259 chname=va_arg(va,char *);
1260 format=va_arg(va,char *);
1261 vsprintf(s,format,va);
1262
1263 if (!*s)
1264 strcpy(s2,empty_string);
1265 else
1266 sprintf(s2,"[%s] %s",s1,s);
1267
1268 if (chname && *chname =='*')
1269 {
1270 if ((f=fopen(logfilen, "a+")) != NULL)
1271 {
1272 fprintf(f,"%s\n",s2);
1273 fclose(f);
1274 }
1275 }
1276 #endif
1277 }
1278
rename_file(char * old_file,char ** new_file)1279 int rename_file(char *old_file, char **new_file)
1280 {
1281 FILE *fp;
1282 char *c, *tmp = NULL;
1283 char buffer[BIG_BUFFER_SIZE];
1284
1285 c = alloca(10);
1286 sprintf(c, "%03i.", getrandom(0, 999));
1287 if (get_string_var(DCC_DLDIR_VAR))
1288 malloc_sprintf(&tmp, "%s/%s", get_string_var(DCC_DLDIR_VAR), c);
1289 else
1290 malloc_sprintf(&tmp, "%s", c);
1291
1292 malloc_strcat(&tmp, *new_file);
1293 strlcpy(buffer, *new_file, sizeof buffer);
1294 while ((fp = fopen(tmp, "r")) != NULL)
1295 {
1296 fclose(fp);
1297 sprintf(c, "%03i.", getrandom(0, 999));
1298 if (get_string_var(DCC_DLDIR_VAR))
1299 malloc_sprintf(&tmp, "%s/%s", get_string_var(DCC_DLDIR_VAR), c);
1300 else
1301 malloc_sprintf(&tmp, "%s", c);
1302 malloc_strcat(&tmp, buffer);
1303 }
1304 if (fp != NULL)
1305 fclose(fp);
1306 malloc_sprintf(new_file, "%s", c);
1307 malloc_strcat(new_file, buffer);
1308 new_free(&tmp);
1309 return 0;
1310 }
1311
isme(char * nick)1312 int isme(char *nick)
1313 {
1314 return ((my_stricmp(nick, get_server_nickname(from_server)) == 0) ? 1 : 0);
1315 }
1316
1317
1318 enum REDIR_TYPES { PRIVMSG = 0, KICK, TOPIC, WALL, WALLOP, NOTICE, KBOOT, KILL, DCC, LIST};
1319 void userhost_ban(UserhostItem *stuff, char *nick1, char *args);
1320
redirect_msg(char * to,enum REDIR_TYPES what,char * str,int showansi)1321 int redirect_msg(char *to, enum REDIR_TYPES what, char *str, int showansi)
1322 {
1323 char *new_str;
1324 if (showansi)
1325 new_str = str;
1326 else
1327 new_str = stripansicodes(str);
1328 switch(what)
1329 {
1330 case PRIVMSG:
1331 if (is_channel(to))
1332 put_it("%s", convert_output_format(fget_string_var(FORMAT_SEND_PUBLIC_FSET), "%s %s %s %s", update_clock(GET_TIME), to, get_server_nickname(from_server), new_str));
1333 else if ((*to == '=') && dcc_activechat(to+1))
1334 ;
1335 else
1336 put_it("%s", convert_output_format(fget_string_var(FORMAT_SEND_MSG_FSET), "%s %s %s %s", update_clock(GET_TIME), to, get_server_nickname(from_server), new_str));
1337 if ((*to == '=') && dcc_activechat(to+1))
1338 dcc_chat_transmit(to+1, new_str, new_str, "PRIVMSG", 1);
1339 else
1340 send_to_server("PRIVMSG %s :%s", to, new_str);
1341 break;
1342 case KILL:
1343 send_to_server("KILL %s :%s", to, new_str);
1344 break;
1345 case KBOOT:
1346 userhostbase(to, userhost_ban, 1, "%s", get_current_channel_by_refnum(0));
1347 case KICK:
1348 send_to_server("KICK %s %s :%s", get_current_channel_by_refnum(0), to, new_str);
1349 break;
1350 case TOPIC:
1351 send_to_server("TOPIC %s :%s", to, new_str);
1352 break;
1353 case WALL:
1354 {
1355 ChanWallOp(NULL, new_str, NULL, NULL);
1356 break;
1357 }
1358 case WALLOP:
1359 put_it("!! %s", str);
1360 send_to_server("WALLOPS :%s", new_str);
1361 break;
1362 case NOTICE:
1363 put_it("%s", convert_output_format(fget_string_var(FORMAT_SEND_NOTICE_FSET), "%s %s %s %s", update_clock(GET_TIME), to, get_server_nickname(from_server), new_str));
1364 send_to_server("NOTICE %s :%s", to, new_str);
1365 break;
1366 case LIST:
1367 default:
1368 break;
1369 }
1370 return 1;
1371 }
1372
BUILT_IN_COMMAND(do_dirlasttype)1373 BUILT_IN_COMMAND(do_dirlasttype)
1374 {
1375 char *channel = NULL; int count = -1;
1376 LastMsg *t = NULL;
1377 char *form = NULL;
1378 char *sform;
1379 int numargs = 5;
1380 int size = 1;
1381 int len = strlen(command);
1382 int showansi = 0;
1383 enum REDIR_TYPES what = PRIVMSG;
1384
1385 if (!my_strnicmp(command, "RELCR", 5))
1386 {
1387 t = &last_ctcp_reply[0];
1388 form = fget_string_var(FORMAT_CTCP_REPLY_FSET);
1389 sform = "%s %s %s %s %s";
1390 if (len == 6 && command[len-1] == 'T')
1391 what = TOPIC;
1392 }
1393 else if (!my_strnicmp(command, "RELC", 4))
1394 {
1395 t = &last_sent_ctcp[0];
1396 form = fget_string_var(FORMAT_SEND_CTCP_FSET);
1397 sform = "%s %s %s %s %s";
1398 if (len > 4 && command[len-1] == 'T')
1399 what = TOPIC;
1400 }
1401 else if (!my_strnicmp(command, "RELD", 4))
1402 {
1403 t = &last_dcc[0];
1404 size = MAX_LAST_MSG;
1405 form = fget_string_var(FORMAT_DCC_CHAT_FSET);
1406 sform = "%s %s %s %s";
1407 if (len > 4 && command[len-1] == 'T')
1408 what = TOPIC;
1409 numargs = 4;
1410 }
1411 else if (!my_strnicmp(command, "RELSD", 5))
1412 {
1413 t = &last_sent_dcc[0];
1414 size = MAX_LAST_MSG;
1415 form = fget_string_var(FORMAT_DCC_CHAT_FSET);
1416 sform = "%s %s %s %s";
1417 if (len > 5 && command[len-1] == 'T')
1418 what = TOPIC;
1419 numargs = 4;
1420 }
1421 else if (!my_strnicmp(command, "RELI", 4))
1422 {
1423 t = &last_invite_channel[0];
1424 form = fget_string_var(FORMAT_INVITE_FSET);
1425 numargs = 4;
1426 sform = "%s %s %s";
1427 if (len > 4 && command[len-1] == 'T')
1428 what = TOPIC;
1429 }
1430 else if (!my_strnicmp(command, "RELM", 4))
1431 {
1432 /* ??? */
1433 t = &last_msg[0]; size = MAX_LAST_MSG;
1434 form = fget_string_var(FORMAT_RELM_FSET);
1435 sform = "%s %s %s %s %s";
1436 if (len > 4 && command[len-1] == 'T')
1437 what = TOPIC;
1438 }
1439 else if (!my_strnicmp(command, "RELN", 4))
1440 {
1441 /* ??? */
1442 t = &last_notice[0]; size = MAX_LAST_MSG;
1443 form = fget_string_var(FORMAT_RELN_FSET);
1444 sform = "%s %s %s %s %s";
1445 if (len > 4 && command[len-1] == 'T')
1446 what = TOPIC;
1447 }
1448 else if (!my_strnicmp(command, "RELSM", 5))
1449 {
1450 /* ??? */
1451 t = &last_sent_msg[0]; size = MAX_LAST_MSG;
1452 form = fget_string_var(FORMAT_RELSM_FSET);
1453 sform = "%s %s %s %s %s";
1454 if (len > 5 && command[len-1] == 'T')
1455 what = TOPIC;
1456 }
1457 else if (!my_strnicmp(command, "RELSN", 5))
1458 {
1459 /* ??? */
1460 t = &last_sent_notice[0]; size = MAX_LAST_MSG;
1461 form = fget_string_var(FORMAT_SEND_NOTICE_FSET);
1462 sform = "%s %s %s %s";
1463 numargs = 4;
1464 if (len > 5 && command[len-1] == 'T')
1465 what = TOPIC;
1466 }
1467 else if (!my_strnicmp(command, "RELST", 5))
1468 {
1469 /* ??? */
1470 t = &last_sent_topic[0];
1471 form = fget_string_var(FORMAT_TOPIC_FSET);
1472 sform = "%s %s %s";
1473 numargs = 2;
1474 if (len > 5 && command[len-1] == 'T')
1475 what = TOPIC;
1476 }
1477 else if (!my_strnicmp(command, "RELSW", 5))
1478 {
1479 /* ??? */
1480 t = &last_sent_wall[0];
1481 form = fget_string_var(FORMAT_WALLOP_FSET);
1482 sform = "%s %s %s %s %s";
1483 if (len > 5 && command[len-1] == 'T')
1484 what = TOPIC;
1485 }
1486 else if (!my_strnicmp(command, "RELS", 4))
1487 {
1488 t = &last_servermsg[0]; size = MAX_LAST_MSG;
1489 form = fget_string_var(FORMAT_RELS_FSET);
1490 sform = "%s %s %s %s";
1491 numargs = 4;
1492 if (len > 4 && command[len-1] == 'T')
1493 what = TOPIC;
1494 }
1495 else if (!my_strnicmp(command, "RELT", 4))
1496 {
1497 /* ??? */
1498 t = &last_topic[0];
1499 form = fget_string_var(FORMAT_TOPIC_FSET);
1500 sform = "%s %s %s";
1501 numargs = 2;
1502 if (len > 4 && command[len-1] == 'T')
1503 what = TOPIC;
1504 }
1505 else if (!my_strnicmp(command, "RELW", 4))
1506 {
1507 /* ??? */
1508 t = &last_wall[0];
1509 size = MAX_LAST_MSG;
1510 form = fget_string_var(FORMAT_WALLOP_FSET);
1511 sform = "%s %s %s %s";
1512 numargs = 4;
1513 if (len > 4 && command[len-1] == 'T')
1514 what = TOPIC;
1515 }
1516 else
1517 {
1518 what = LIST; size = MAX_LAST_MSG;
1519 t = &last_msg[0];
1520 for (count = size - 1; count != -1; count--)
1521 {
1522 if (t[count].last_msg)
1523 put_it("%2d %s", count, convert_output_format(fget_string_var(FORMAT_RELM_FSET), "%s %s %s %s %s", t[count].time, t[count].from, t[count].uh, t[count].to, t[count].last_msg));
1524 }
1525 return;
1526 }
1527
1528 while (args && *args)
1529 {
1530 char *comm;
1531 if (!(comm = next_arg(args, &args)))
1532 break;
1533 if (!my_strnicmp(comm, "-list", strlen(comm)))
1534 {
1535 for (count = size - 1; count != -1; count--)
1536 {
1537 if (!t[count].last_msg)
1538 continue;
1539 switch(numargs)
1540 {
1541 case 2:
1542 put_it("%2d %s", count, convert_output_format(form, sform, t[count].time, t[count].to, t[count].last_msg));
1543 break;
1544 case 3:
1545 put_it("%2d %s", count, convert_output_format(form, sform, t[count].time, t[count].from, t[count].last_msg));
1546 break;
1547 case 4:
1548 put_it("%2d %s", count, convert_output_format(form, sform, t[count].time, t[count].from, t[count].to, t[count].last_msg));
1549 break;
1550 case 5:
1551 put_it("%2d %s", count, convert_output_format(form, sform, t[count].time, t[count].from, t[count].uh, t[count].to, t[count].last_msg));
1552 }
1553 }
1554 return;
1555 }
1556 else if (!my_strnicmp(comm, "-kick", strlen(comm)))
1557 what = KICK;
1558 else if (!my_strnicmp(comm, "-wall", strlen(comm)))
1559 what = WALL;
1560 else if (!my_strnicmp(comm, "-wallop", strlen(comm)))
1561 what = WALLOP;
1562 else if (!my_strnicmp(comm, "-msg", strlen(comm)))
1563 what = PRIVMSG;
1564 else if (!my_strnicmp(comm, "-notice", strlen(comm)))
1565 what = NOTICE;
1566 else if (!my_strnicmp(comm, "-topic", strlen(comm)))
1567 what = TOPIC;
1568 else if (!my_strnicmp(comm, "-kboot", strlen(comm)))
1569 what = KBOOT;
1570 else if (!my_strnicmp(comm, "-kill", strlen(comm)))
1571 what = KILL;
1572 else if (!my_strnicmp(comm, "-ansi", strlen(comm)))
1573 showansi++;
1574 else if (!my_strnicmp(comm, "-num", strlen(comm)))
1575 {
1576 comm = next_arg(args, &args);
1577 if (is_number(comm))
1578 {
1579 count = my_atol(comm);
1580 if (count < 0)
1581 count *= -1;
1582 }
1583 else
1584 channel = comm;
1585 }
1586 else
1587 channel = comm;
1588
1589 if (count > size)
1590 count = size;
1591 }
1592 if (count == -1)
1593 count = 0;
1594 if (!channel)
1595 channel = get_target_by_refnum(0);
1596 if (channel || what == WALLOP)
1597 {
1598 char *p = NULL;
1599 if (!t[count].last_msg)
1600 {
1601 bitchsay("No such msg #%d for /%s received", count, command);
1602 return;
1603 }
1604 switch(numargs)
1605 {
1606 case 2:
1607 malloc_strcpy(&p, convert_output_format(form, sform, t[count].time, t[count].to, t[count].last_msg));
1608 break;
1609 case 3:
1610 malloc_strcpy(&p, convert_output_format(form, sform, t[count].time, t[count].from, t[count].last_msg));
1611 break;
1612 case 4:
1613 malloc_strcpy(&p, convert_output_format(form, sform, t[count].time, t[count].from, t[count].to, t[count].last_msg));
1614 break;
1615 case 5:
1616 malloc_strcpy(&p, convert_output_format(form, sform, t[count].time, t[count].from, t[count].uh, t[count].to, t[count].last_msg));
1617 }
1618 redirect_msg(channel, what, p, showansi);
1619 new_free(&p);
1620 }
1621 else
1622 bitchsay("Can not %s what you requested", command);
1623 }
1624
1625 /*
1626 * Wallop Sends NOTICE to all ops of Current Channel!
1627 */
BUILT_IN_COMMAND(ChanWallOp)1628 BUILT_IN_COMMAND(ChanWallOp)
1629 {
1630 char *channel = NULL;
1631 char *chops = NULL;
1632 char *include = NULL;
1633 char *exclude = NULL;
1634 ChannelList *chan;
1635 NickList *tmp;
1636 int ver = 0;
1637 int enable_all = 0;
1638
1639 char buffer[BIG_BUFFER_SIZE + 1];
1640
1641 if (!args || (args && !*args))
1642 return;
1643
1644 if (get_current_channel_by_refnum(0))
1645 {
1646 int count = 0;
1647 int i = 0;
1648 char *nick = NULL;
1649 malloc_strcpy(&channel, get_current_channel_by_refnum(0));
1650 chan = lookup_channel(channel, current_window->server, 0);
1651 if (((ver = get_server_version(current_window->server)) == Server2_8hybrid6))
1652 enable_all = 1;
1653 else if (((ver = get_server_version(current_window->server)) < Server_u2_8))
1654 {
1655 while (args && (*args == '-' || *args == '+'))
1656 {
1657 nick = next_arg(args, &args);
1658 if (*nick == '-')
1659 {
1660 malloc_strcat(&exclude, nick+1);
1661 malloc_strcat(&exclude, space);
1662 }
1663 else
1664 {
1665 malloc_strcat(&include, nick+1);
1666 malloc_strcat(&include, space);
1667 }
1668 }
1669 }
1670 if (!args || !*args)
1671 {
1672 bitchsay("NO Wallmsg included");
1673 new_free(&exclude);
1674 new_free(&include);
1675 new_free(&channel);
1676 }
1677 set_display_target(channel, LOG_WALL);
1678 sprintf(buffer, "[\002BX-Wall\002/\002%s\002] %s", channel, args);
1679 if (ver >= Server_u2_10 || enable_all)
1680 {
1681 send_to_server(enable_all?"NOTICE @%s :%s":"WALLCHOPS %s :%s", channel, buffer);
1682 put_it("%s", convert_output_format(fget_string_var(FORMAT_BWALL_FSET), "%s %s %s %s %s", update_clock(GET_TIME), channel, "*", "*", args));
1683 add_last_type(&last_sent_wall[0], 1, NULL, NULL, channel, buffer);
1684 new_free(&channel);
1685 reset_display_target();
1686 return;
1687 }
1688 for (tmp = next_nicklist(chan, NULL); tmp; tmp = next_nicklist(chan, tmp))
1689 {
1690 if (!my_stricmp(tmp->nick, get_server_nickname(from_server)))
1691 continue;
1692 if (exclude && stristr(exclude, tmp->nick))
1693 continue;
1694 if (nick_isop(tmp) || (include && stristr(include, tmp->nick)))
1695 {
1696 if (chops)
1697 malloc_strcat(&chops, ",");
1698 malloc_strcat(&chops, tmp->nick);
1699 count++;
1700 }
1701 if (count >= 8 && chops)
1702 {
1703 send_to_server("%s %s :%s", "NOTICE", chops, buffer);
1704 i+=count;
1705 count = 0;
1706 new_free(&chops);
1707 }
1708 }
1709 i+=count;
1710 if (chops)
1711 send_to_server("%s %s :%s", "NOTICE", chops, buffer);
1712 if (i)
1713 {
1714 put_it("%s", convert_output_format(fget_string_var(FORMAT_BWALL_FSET), "%s %s %s %s %s", update_clock(GET_TIME), channel, "*", "*", args));
1715 add_last_type(&last_sent_wall[0], 1, NULL, NULL, channel, buffer);
1716 if (exclude)
1717 bitchsay("Excluded <%s> from wallmsg", exclude);
1718 if (include)
1719 bitchsay("Included <%s> in wallmsg", include);
1720 }
1721 else
1722 put_it("%s", convert_output_format("$G No ops on $0", "%s", channel));
1723 reset_display_target();
1724 }
1725 else
1726 say("No Current Channel for this Window.");
1727 new_free(&include);
1728 new_free(&channel);
1729 new_free(&chops);
1730 new_free(&exclude);
1731 }
1732
log_toggle(int flag,ChannelList * chan)1733 void log_toggle(int flag, ChannelList *chan)
1734 {
1735 char *logfile;
1736
1737 if (((logfile = get_string_var(MSGLOGFILE_VAR)) == NULL) || !get_string_var(CTOOLZ_DIR_VAR))
1738 {
1739 bitchsay("You must set the MSGLOGFILE and CTOOLZ_DIR variables first!");
1740 set_int_var(MSGLOG_VAR, 0);
1741 return;
1742 }
1743 logmsg(LOG_CURRENT, NULL, flag ? 1 : 2, NULL);
1744 }
1745
are_you_opped(char * channel)1746 int are_you_opped(char *channel)
1747 {
1748 return is_chanop(channel, get_server_nickname(from_server));
1749 }
1750
error_not_opped(const char * channel)1751 void error_not_opped(const char *channel)
1752 {
1753 set_display_target(channel, LOG_CRAP);
1754 say("You're not opped on %s", channel);
1755 reset_display_target();
1756 }
1757
freadln(FILE * stream,char * lin)1758 int freadln(FILE *stream, char *lin)
1759 {
1760 char *p;
1761
1762 do
1763 p = fgets(lin, IRCD_BUFFER_SIZE/4, stream);
1764 while (p && (*lin == '#'));
1765
1766 if (!p)
1767 return 0;
1768 chop(lin, 1);
1769 if (!*lin)
1770 return 0;
1771 return 1;
1772 }
1773
randreason(char * filename)1774 char *randreason(char *filename)
1775 {
1776 int count, min, i;
1777 FILE *bleah;
1778 char *f = NULL;
1779 static char buffer[IRCD_BUFFER_SIZE/4 + 1];
1780
1781 min = 1;
1782 count = 0;
1783
1784 buffer[0] = '\0';
1785 f = m_strdup(filename);
1786 if (filename && (bleah = uzfopen(&f, get_string_var(LOAD_PATH_VAR), 0)))
1787 {
1788 while (!feof(bleah))
1789 if (freadln(bleah, buffer))
1790 count++;
1791 if (!count)
1792 {
1793 strcpy(buffer, "No Reason");
1794 new_free(&f);
1795 return buffer;
1796 }
1797 i = getrandom(1, count);
1798 count = 0;
1799 fclose(bleah);
1800 bleah = uzfopen(&f, get_string_var(LOAD_PATH_VAR), 0);
1801 while (!feof(bleah) && (count < i))
1802 if (freadln(bleah, buffer))
1803 count++;
1804 fclose(bleah);
1805 }
1806 new_free(&f);
1807 if (*buffer)
1808 return buffer;
1809 return NULL;
1810 }
1811
get_reason(char * nick,char * file)1812 char *get_reason(char *nick, char *file)
1813 {
1814 char *temp;
1815 char *filename = NULL;
1816 if (file && *file)
1817 malloc_strcpy(&filename, file);
1818 else
1819 malloc_sprintf(&filename, "%s", DEFAULT_BITCHX_KICK_FILE);
1820 temp = randreason(filename);
1821 new_free(&filename);
1822 if ((!temp || !*temp) && get_string_var(DEFAULT_REASON_VAR))
1823 temp = get_string_var(DEFAULT_REASON_VAR);
1824 return (stripansicodes(convert_output_format(temp, "%s %s", nick? nick: "error", get_server_nickname(from_server) )));
1825 }
1826
get_realname(char * nick)1827 char *get_realname(char *nick)
1828 {
1829 char *temp;
1830 char *filename = NULL;
1831
1832 malloc_sprintf(&filename, "%s", DEFAULT_BITCHX_IRCNAME_FILE);
1833 temp = randreason(filename);
1834 new_free(&filename);
1835 if ((!temp || !*temp))
1836 temp = "Who cares?";
1837 return (stripansicodes(convert_output_format(temp, "%s %s", nick? nick: "error", get_server_nickname(from_server) )));
1838 }
1839
get_signoffreason(char * nick)1840 char *get_signoffreason(char *nick)
1841 {
1842 char *temp;
1843 char *filename = NULL;
1844
1845 malloc_sprintf(&filename, "%s", DEFAULT_BITCHX_QUIT_FILE);
1846 temp = randreason(filename);
1847 new_free(&filename);
1848 if (!temp || !*temp)
1849 temp = "$0 has no reason";
1850 return (stripansicodes(convert_output_format(temp, "%s %s", nick? nick: "error", get_server_nickname(from_server))));
1851 }
1852
1853 #ifdef WANT_NSLOOKUP
1854
auto_nslookup(struct reslist * rptr)1855 void auto_nslookup(struct reslist *rptr)
1856 {
1857 NickList *nick;
1858 ChannelList *chan;
1859 struct in_addr ip;
1860
1861 if ((chan = lookup_channel(rptr->channel, rptr->server, 0)))
1862 {
1863 if ((nick = find_nicklist_in_channellist(rptr->nick, chan, 0)))
1864 {
1865 if (rptr->re_he.h_addr_list[0].s_addr)
1866 {
1867 bcopy(&rptr->re_he.h_addr_list[0], (char *)&ip, sizeof(ip));
1868 nick->ip = m_strdup(inet_ntoa(ip));
1869 #ifdef WANT_USERLIST
1870 check_auto(chan->channel, nick, chan);
1871 #endif
1872 }
1873 else if (++nick->ip_count < 2)
1874 do_nslookup(rptr->host, rptr->nick, rptr->user, rptr->channel, rptr->server, auto_nslookup, NULL);
1875 #ifdef PANA_DEBUG
1876 else
1877 put_it("got here. nslookup failure %s!%s", nick->nick, nick->host);
1878 #endif
1879 }
1880 }
1881 return;
1882 }
1883
print_ns_succede(struct reslist * rptr)1884 void print_ns_succede(struct reslist *rptr)
1885 {
1886 char *u, *n, *h;
1887 char buffer[BIG_BUFFER_SIZE];
1888 struct in_addr ip;
1889 u = rptr->user ? rptr->user : empty_string;
1890 h = rptr->host;
1891 n = rptr->nick ? rptr->nick : empty_string;
1892 if (rptr->command)
1893 {
1894 int i;
1895 if (rptr->nick && rptr->user)
1896 sprintf(buffer, "%s!%s@%s ", n, u, h);
1897 else
1898 sprintf(buffer, "%s ", h);
1899 for (i = 0; rptr->re_he.h_addr_list[i].s_addr; i++)
1900 {
1901 bcopy(&rptr->re_he.h_addr_list[i], (char *)&ip, sizeof(ip));
1902 BX_strpcat(buffer, "%s ", inet_ntoa(ip));
1903 if (strlen(buffer) > 490)
1904 break;
1905 }
1906 parse_line("NSLOOKUP", rptr->command, buffer, 0, 0, 1);
1907 return;
1908 }
1909 if (do_hook(NSLOOKUP_LIST, "%s %s %s %s %s", h, rptr->re_he.h_name?rptr->re_he.h_name:empty_string, (char *)inet_ntoa(rptr->re_he.h_addr_list[0]), n, u))
1910 {
1911 int i;
1912 *buffer = 0;
1913 if (rptr->nick && rptr->user)
1914 bitchsay("[%s!%s@%s]: %s", n, u, h, rptr->re_he.h_name ? rptr->re_he.h_name: "invalid hostname");
1915 else
1916 bitchsay("%s is %s (%s)", h, rptr->re_he.h_name ? rptr->re_he.h_name:"invalid hostname", (char *)inet_ntoa(rptr->re_he.h_addr_list[0]));
1917 for (i = 0; rptr->re_he.h_addr_list[i].s_addr; i++)
1918 {
1919 bcopy(&rptr->re_he.h_addr_list[i], (char *)&ip, sizeof(ip));
1920 BX_strpcat(buffer, "[%s] ", inet_ntoa(ip));
1921 if (strlen(buffer) > 490)
1922 break;
1923 }
1924 bitchsay("IPs: %s", buffer);
1925 for (i = 0; rptr->re_he.h_aliases[i]; i++)
1926 bitchsay("\talias %d = %s", i+1, rptr->re_he.h_aliases[i]);
1927 }
1928 }
1929
print_ns_fail(struct reslist * rptr)1930 void print_ns_fail(struct reslist *rptr)
1931 {
1932 if (rptr->command)
1933 {
1934 char buffer[BIG_BUFFER_SIZE];
1935 if (rptr->nick && rptr->user)
1936 sprintf(buffer, "%s!%s@%s ", rptr->nick, rptr->user, rptr->host);
1937 else
1938 sprintf(buffer, "%s ", rptr->host);
1939 parse_line("NSLOOKUP", rptr->command, buffer, 0, 0, 1);
1940 return;
1941 }
1942 if (do_hook(NSLOOKUP_LIST, "%s %s %s", rptr->host, rptr->nick?rptr->nick:empty_string, rptr->user?rptr->user:empty_string))
1943 {
1944 if (rptr->nick && rptr->user)
1945 bitchsay("nslookup of %s!%s@%s failed.", rptr->nick, rptr->user, rptr->host);
1946 else
1947 bitchsay("nslookup of host %s failed.", rptr->host);
1948 }
1949 }
1950 #ifdef THREAD
1951
1952 /* Threaded generic callback to convert from Sheik's
1953 * return format to the one that is already used in
1954 * BitchX to maintain threaded and non-threaded
1955 * compatibility.
1956 */
cdns_generic_callback(DNS_QUEUE * dns)1957 void cdns_generic_callback(DNS_QUEUE *dns)
1958 {
1959 struct reslist *info = dns->callinfo;
1960
1961 if(!info)
1962 return;
1963
1964 if(dns->hostentr)
1965 memcpy(&info->re_he, dns->hostentr, sizeof(struct hent));
1966
1967 if(info->func)
1968 info->func(info);
1969 else if(dns->out)
1970 print_ns_succede(info);
1971 else
1972 print_ns_fail(info);
1973
1974 new_free(&info->nick);
1975 new_free(&info->user);
1976 new_free(&info->host);
1977 new_free(&info->channel);
1978 new_free(&info->command);
1979 new_free(&info);
1980 }
1981
1982 /* Not entirely sure how to handle this at the moment */
ar_rename_nick(char * old_nick,char * new_nick,int server)1983 void ar_rename_nick(char *old_nick, char *new_nick, int server)
1984 {
1985 }
1986
1987 #else
1988
1989
1990 /*
1991 * arlib.c (C)opyright 1993 Darren Reed. All rights reserved.
1992 * This file may not be distributed without the author's permission in any
1993 * shape or form. The author takes no responsibility for any damage or loss
1994 * of property which results from the use of this software.
1995 * heavily modified for use in a irc client.
1996 */
1997
1998 #if !defined( __APPLE__ )
1999 /* On some systems, eg OpenBSD, we have to define BIND_4_COMPAT to get
2000 * nameser_compat.h included, to get the "old" bind interface. */
2001 #if !defined( BIND_4_COMPAT )
2002 #define BIND_4_COMPAT
2003 #endif
2004 #else
2005 /* After one too many bongs some developer at Apple decided to rename this
2006 * macro for no good reason. */
2007 #if !defined( BIND_8_COMPAT )
2008 #define BIND_8_COMPAT
2009 #endif
2010 #endif
2011
2012 #include <stdio.h>
2013 #include <fcntl.h>
2014 #include <signal.h>
2015 #include <sys/types.h>
2016 #include <sys/time.h>
2017 #include <sys/socket.h>
2018 #include <netinet/in.h>
2019 #include <netdb.h>
2020 #include <arpa/nameser.h>
2021 #include <resolv.h>
2022
2023 #define HOSTLEN 100
2024 extern int h_errno;
2025 static char ar_hostbuf[HOSTLEN+1], ar_domainname[HOSTLEN+1];
2026 static char ar_dot[] = ".";
2027 static int ar_resfd = -1, ar_vc = 0;
2028 static struct reslist *ar_last = NULL, *ar_first = NULL;
2029
2030
2031 static int do_query_name(struct resinfo *, char *, register struct reslist *, char *, char *, char *, char *, int , void (*func)(), char *);
2032 static int do_query_number(struct resinfo *, char *, register struct reslist *, char *, char *, char *, char *, int , void (*func)(), char *);
2033 static int ar_resend_query(struct reslist *);
2034
2035 #define MAX_RETRIES 4
2036
2037 #ifndef HFIXEDSZ
2038 #define HFIXEDSZ 12
2039 #endif
2040
2041 #ifndef INT32SZ
2042 #define INT32SZ 4
2043 #endif
2044
2045
2046 /*
2047 * Statistics structure.
2048 */
2049 static struct resstats {
2050 int re_errors;
2051 int re_nu_look;
2052 int re_na_look;
2053 int re_replies;
2054 int re_requests;
2055 int re_resends;
2056 int re_sent;
2057 int re_timeouts;
2058 } ar_reinfo;
2059
2060 #ifdef HAVE_LIBIPHLPAPI
2061
ar_get_windows_dns(void)2062 void ar_get_windows_dns(void)
2063 {
2064 DWORD ret;
2065 ULONG buflen = 0;
2066 FIXED_INFO *buf;
2067
2068 ret = GetNetworkParams(NULL, &buflen);
2069 if (ret != ERROR_BUFFER_OVERFLOW)
2070 return;
2071
2072 buf = new_malloc(buflen);
2073
2074 ret = GetNetworkParams(buf, &buflen);
2075 if (ret == NO_ERROR)
2076 {
2077 _res.nscount = 1;
2078 _res.nsaddr_list[0].sin_family = AF_INET;
2079 _res.nsaddr_list[0].sin_addr.s_addr = inet_addr(buf->DnsServerList.IpAddress.String);
2080 _res.nsaddr_list[0].sin_port = htons(53);
2081 }
2082
2083 new_free(&buf);
2084 return;
2085 }
2086 #endif /* HAVE_LIBIPHLPAPI */
2087
2088 /*
2089 * ar_init
2090 *
2091 * Initializes the various ARLIB internal varilables and related DNS
2092 * options for res_init().
2093 *
2094 * Returns 0 or the socket opened for use with talking to name servers
2095 * if 0 is passed or ARES_INITSOCK is set.
2096 */
ar_init(int op)2097 int ar_init(int op)
2098 {
2099 int ret = 0;
2100
2101 if (!op)
2102 return ar_resfd;
2103 if (op & ARES_INITLIST)
2104 {
2105 memset(&ar_reinfo, 0, sizeof(ar_reinfo));
2106 ar_first = ar_last = NULL;
2107 }
2108
2109 if (op & ARES_CALLINIT && !(_res.options & RES_INIT))
2110 {
2111 ret = res_init();
2112 (void)strcpy(ar_domainname, ar_dot);
2113 (void)strncat(ar_domainname, _res.defdname, HOSTLEN-2);
2114 #ifdef HAVE_LIBIPHLPAPI
2115 /* The Cygwin resolver library doesn't fill out _res.nsaddr_list
2116 * and sets _res.nscount to -1 if there's no /etc/resolv.conf file,
2117 * so we try fetching the first DNS server address ourselves. */
2118 if (_res.nscount < 1)
2119 ar_get_windows_dns();
2120 #endif
2121 if (_res.nscount < 1)
2122 {
2123 /* Try falling back to the Google public DNS */
2124 _res.nscount = 1;
2125 _res.nsaddr_list[0].sin_family = AF_INET;
2126 _res.nsaddr_list[0].sin_addr.s_addr = inet_addr("8.8.8.8");
2127 _res.nsaddr_list[0].sin_port = htons(53);
2128 }
2129 }
2130
2131 if (op & ARES_INITSOCK)
2132 ret = ar_resfd = ar_open();
2133
2134 if (op & ARES_INITDEBG)
2135 _res.options |= RES_DEBUG;
2136 return ret;
2137 }
2138
2139 /*
2140 * ar_open
2141 *
2142 * Open a socket to talk to a name server with.
2143 * Check _res.options to see if we use a TCP or UDP socket.
2144 */
ar_open(void)2145 int ar_open(void)
2146 {
2147 if (ar_resfd > -1)
2148 return ar_resfd;
2149
2150 if (_res.options & RES_USEVC)
2151 {
2152 struct sockaddr_in *sip;
2153 int i = 0;
2154
2155 sip = _res.nsaddr_list;
2156 ar_vc = 1;
2157 ar_resfd = socket(AF_INET, SOCK_STREAM, 0);
2158
2159 /*
2160 * Try each name server listed in sequence until we
2161 * succeed or run out.
2162 */
2163 while (connect(ar_resfd, (struct sockaddr *)sip++,
2164 sizeof(struct sockaddr)))
2165 {
2166 (void)close(ar_resfd);
2167 ar_resfd = -1;
2168 if (i >= _res.nscount)
2169 break;
2170 ar_resfd = socket(AF_INET, SOCK_STREAM, 0);
2171 }
2172 }
2173 else
2174 {
2175 int on = 0;
2176 ar_resfd = socket(AF_INET, SOCK_DGRAM, 0);
2177
2178 if (ar_resfd > -1)
2179 (void) setsockopt(ar_resfd, SOL_SOCKET, SO_BROADCAST,(char *)&on, sizeof(on));
2180 }
2181
2182 if (ar_resfd < 0)
2183 return -1;
2184
2185 if (set_non_blocking(ar_resfd) < 0)
2186 {
2187 (void)close(ar_resfd);
2188 ar_resfd = -1;
2189 }
2190
2191 return new_open(ar_resfd);
2192 }
2193
2194 /*
2195 * ar_close
2196 *
2197 * Closes and flags the ARLIB socket as closed.
2198 */
ar_close(void)2199 void ar_close(void)
2200 {
2201 new_close(ar_resfd);
2202 ar_resfd = -1;
2203 return;
2204 }
2205
2206 /*
2207 * ar_add_request
2208 *
2209 * Add a new DNS query to the end of the query list.
2210 */
ar_add_request(struct reslist * new)2211 static int ar_add_request(struct reslist *new)
2212 {
2213 if (!new)
2214 return -1;
2215 if (!ar_first)
2216 ar_first = ar_last = new;
2217 else
2218 {
2219 ar_last->re_next = new;
2220 ar_last = new;
2221 }
2222 new->re_next = NULL;
2223 ar_reinfo.re_requests++;
2224 return 0;
2225 }
2226
2227 /*
2228 * ar_remrequest
2229 *
2230 * Remove a request from the list. This must also free any memory that has
2231 * been allocated for temporary storage of DNS results.
2232 *
2233 * Returns -1 if there are anyy problems removing the requested structure
2234 * or 0 if the remove is successful.
2235 */
ar_remrequest(struct reslist * old)2236 static int ar_remrequest(struct reslist *old)
2237 {
2238 struct reslist *rptr, *r2ptr;
2239 register char **s;
2240
2241 if (!old)
2242 return -1;
2243 for (rptr = ar_first, r2ptr = NULL; rptr; rptr = rptr->re_next)
2244 {
2245 if (rptr == old)
2246 break;
2247 r2ptr = rptr;
2248 }
2249
2250 if (!rptr)
2251 return -1;
2252 if (rptr == ar_first)
2253 ar_first = ar_first->re_next;
2254 else if (rptr == ar_last)
2255 {
2256 if ((ar_last = r2ptr))
2257 ar_last->re_next = NULL;
2258 }
2259 else
2260 r2ptr->re_next = rptr->re_next;
2261
2262 if (!ar_first)
2263 ar_last = ar_first;
2264 if (rptr->re_he.h_name)
2265 new_free(&rptr->re_he.h_name);
2266 if ((s = rptr->re_he.h_aliases))
2267 {
2268 for (; *s; s++)
2269 new_free(s);
2270 }
2271 if (rptr->re_rinfo.ri_ptr)
2272 new_free(&rptr->re_rinfo.ri_ptr);
2273
2274 new_free(&rptr->nick);
2275 new_free(&rptr->user);
2276 new_free(&rptr->host);
2277 new_free(&rptr->channel);
2278 new_free(&rptr->command);
2279 new_free(&rptr);
2280
2281 return 0;
2282 }
2283
2284 /*
2285 * ar_make_request
2286 *
2287 * Create a DNS query recorded for the request being made and place it on the
2288 * current list awaiting replies. Initialization of the record with set
2289 * values should also be done.
2290 */
ar_make_request(register struct resinfo * resi,char * nick,char * user,char * h,char * chan,int server,void (* func)(),char * command)2291 static struct reslist *ar_make_request(register struct resinfo *resi, char *nick, char *user, char *h, char *chan, int server, void (*func)(), char *command)
2292 {
2293 register struct reslist *rptr;
2294 register struct resinfo *rp;
2295
2296 rptr = (struct reslist *)new_malloc(sizeof(struct reslist));
2297 rp = &rptr->re_rinfo;
2298
2299 rptr->re_next = NULL; /* where NULL is non-zero ;) */
2300 rptr->re_sentat = now;
2301 rptr->re_retries = MAX_RETRIES;/*_res.retry + 2;*/
2302 rptr->re_sends = 1;
2303 rptr->re_resend = 1;
2304 rptr->re_timeout = rptr->re_sentat + _res.retrans;
2305 rptr->re_he.h_name = NULL;
2306 rptr->re_he.h_addrtype = AF_INET;
2307 rptr->re_he.h_aliases[0] = NULL;
2308 rp->ri_ptr = resi->ri_ptr;
2309 rp->ri_size = resi->ri_size;
2310 if (nick)
2311 malloc_strcpy(&rptr->nick, nick);
2312 if (user)
2313 malloc_strcpy(&rptr->user, user);
2314 if (h)
2315 malloc_strcpy(&rptr->host, h);
2316 if (chan)
2317 rptr->channel = m_strdup(chan);
2318 if (command)
2319 rptr->command = m_strdup(command);
2320 rptr->server = server;
2321 if (func)
2322 rptr->func = func;
2323 (void)ar_add_request(rptr);
2324
2325 return rptr;
2326 }
2327
ar_rename_nick(char * old_nick,char * new_nick,int server)2328 void ar_rename_nick(char *old_nick, char *new_nick, int server)
2329 {
2330 register struct reslist *rptr;
2331 for (rptr = ar_first; rptr; rptr = rptr->re_next)
2332 {
2333 if (!rptr->nick) continue;
2334 if (!strcmp(rptr->nick, old_nick) && rptr->server == server)
2335 malloc_strcpy(&rptr->nick, new_nick);
2336 }
2337 }
2338
2339 /*
2340 * ar_timeout
2341 *
2342 * Remove queries from the list which have been there too long without
2343 * being resolved.
2344 */
ar_timeout(time_t now,char * info,int size,void (* func)(struct reslist *))2345 long ar_timeout(time_t now, char *info, int size, void (*func)(struct reslist *) )
2346 {
2347 register struct reslist *rptr, *r2ptr;
2348 register long next = 0;
2349
2350 for (rptr = ar_first, r2ptr = NULL; rptr; rptr = r2ptr)
2351 {
2352 r2ptr = rptr->re_next;
2353 if (now >= rptr->re_timeout)
2354 {
2355 /*
2356 * If the timeout for the query has been exceeded,
2357 * then resend the query if we still have some
2358 * 'retry credit' and reset the timeout. If we have
2359 * used it all up, then remove the request.
2360 */
2361 if (--rptr->re_retries <= 0)
2362 {
2363 ar_reinfo.re_timeouts++;
2364 if (info && rptr->re_rinfo.ri_ptr)
2365 bcopy(rptr->re_rinfo.ri_ptr, info,
2366 MIN(rptr->re_rinfo.ri_size, size));
2367 if (rptr->func)
2368 (*rptr->func)(rptr);
2369 else if (func)
2370 (*func)(rptr);
2371 (void)ar_remrequest(rptr);
2372 return now;
2373 }
2374 else
2375 {
2376 rptr->re_sends++;
2377 rptr->re_sentat = now;
2378 rptr->re_timeout = now + _res.retrans;
2379 (void)ar_resend_query(rptr);
2380 }
2381 }
2382 if (!next || rptr->re_timeout < next)
2383 next = rptr->re_timeout;
2384 }
2385 return next;
2386 }
2387
2388 /*
2389 * ar_send_res_msg
2390 *
2391 * When sending queries to nameservers listed in the resolv.conf file,
2392 * don't send a query to every one, but increase the number sent linearly
2393 * to match the number of resends. This increase only occurs if there are
2394 * multiple nameserver entries in the resolv.conf file.
2395 * The return value is the number of messages successfully sent to
2396 * nameservers or -1 if no successful sends.
2397 */
ar_send_res_msg(char * msg,int len,int rcount)2398 static int ar_send_res_msg(char *msg, int len, int rcount)
2399 {
2400 register int i;
2401 int sent = 0;
2402
2403 if (!msg)
2404 return -1;
2405
2406 rcount = (_res.nscount > rcount) ? rcount : _res.nscount;
2407 if (_res.options & RES_PRIMARY)
2408 rcount = 1;
2409 if (!rcount)
2410 rcount = 1;
2411 if (ar_vc)
2412 {
2413 ar_reinfo.re_sent++;
2414 sent++;
2415 if (write(ar_resfd, msg, len) == -1)
2416 {
2417 int errtmp = errno;
2418 ar_close();
2419 errno = errtmp;
2420 }
2421 }
2422 else
2423 for (i = 0; i < rcount; i++)
2424 {
2425 _res.nsaddr_list[i].sin_family = AF_INET;
2426 if (sendto(ar_resfd, msg, len, 0,
2427 (struct sockaddr *)&(_res.nsaddr_list[i]),
2428 sizeof(struct sockaddr_in)) == len)
2429 {
2430 ar_reinfo.re_sent++;
2431 sent++;
2432 }
2433 }
2434 return (sent) ? sent : -1;
2435 }
2436
2437 /*
2438 * ar_find_id
2439 *
2440 * find a dns query record by the id (id is determined by dn_mkquery)
2441 */
ar_find_id(int id)2442 static struct reslist *ar_find_id(int id)
2443 {
2444 register struct reslist *rptr;
2445
2446 for (rptr = ar_first; rptr; rptr = rptr->re_next)
2447 if (rptr->re_id == id)
2448 return rptr;
2449 return NULL;
2450 }
2451
2452 /*
2453 * ar_delete
2454 *
2455 * Delete a request from the waiting list if it has a data pointer which
2456 * matches the one passed.
2457 */
ar_delete(char * ptr,int size)2458 int ar_delete(char *ptr, int size)
2459 {
2460 register struct reslist *rptr;
2461 register struct reslist *r2ptr;
2462 int removed = 0;
2463
2464 for (rptr = ar_first; rptr; rptr = r2ptr)
2465 {
2466 r2ptr = rptr->re_next;
2467 if (rptr->re_rinfo.ri_ptr && ptr && size &&
2468 memcmp(rptr->re_rinfo.ri_ptr, ptr, size) == 0)
2469 {
2470 (void)ar_remrequest(rptr);
2471 removed++;
2472 }
2473 }
2474 return removed;
2475 }
2476
2477 /*
2478 * ar_query_name
2479 *
2480 * generate a query based on class, type and name.
2481 */
ar_query_name(char * name,int class,int type,struct reslist * rptr)2482 static int ar_query_name(char *name, int class, int type, struct reslist *rptr)
2483 {
2484 static char buf[MAXPACKET];
2485 int r,s;
2486 HEADER *hptr;
2487
2488 memset(buf, 0, sizeof(buf));
2489 r = res_mkquery(QUERY, name, class, type, NULL, 0, NULL,
2490 buf, sizeof(buf));
2491 if (r <= 0)
2492 {
2493 h_errno = NO_RECOVERY;
2494 return r;
2495 }
2496 hptr = (HEADER *)buf;
2497 rptr->re_id = ntohs(hptr->id);
2498
2499 s = ar_send_res_msg(buf, r, rptr->re_sends);
2500
2501 if (s == -1)
2502 {
2503 h_errno = TRY_AGAIN;
2504 return -1;
2505 }
2506 else
2507 rptr->re_sent += s;
2508 return 0;
2509 }
2510
2511 /*
2512 * ar_gethostbyname
2513 *
2514 * Replacement library function call to gethostbyname(). This one, however,
2515 * doesn't return the record being looked up but just places the query in the
2516 * queue to await answers.
2517 */
ar_gethostbyname(char * name,char * info,int size,char * nick,char * user,char * h,char * chan,int server,void (* func)(),char * command)2518 int ar_gethostbyname(char *name, char *info, int size, char *nick, char *user, char *h, char *chan, int server, void (*func)(), char *command)
2519 {
2520 char host[HOSTLEN+1];
2521 struct resinfo resi;
2522 register struct resinfo *rp = &resi;
2523
2524 if (size && info)
2525 {
2526 rp->ri_ptr = (char *)new_malloc(size+1);
2527 if (*info)
2528 bcopy(info, rp->ri_ptr, size);
2529 rp->ri_size = size;
2530 }
2531 else
2532 memset((char *)rp, 0, sizeof(resi));
2533 ar_reinfo.re_na_look++;
2534 (void)strncpy(host, name, 64);
2535 host[64] = '\0';
2536
2537 return (do_query_name(rp, host, NULL, nick, user, h, chan, server, func, command));
2538 }
2539
do_query_name(struct resinfo * resi,char * name,register struct reslist * rptr,char * nick,char * user,char * h,char * chan,int server,void (* func)(),char * command)2540 static int do_query_name(struct resinfo *resi, char *name, register struct reslist *rptr, char *nick, char *user, char *h, char *chan, int server, void (*func)(), char *command)
2541 {
2542 char hname[HOSTLEN];
2543 int len;
2544
2545 len = strlen((char *)strncpy(hname, name, sizeof(hname)-1));
2546
2547 if (rptr && (hname[len-1] != '.'))
2548 {
2549 (void)strncat(hname, ar_dot, sizeof(hname)-len-1);
2550 /*
2551 * NOTE: The logical relationship between DNSRCH and DEFNAMES
2552 * is implies. ie no DEFNAES, no DNSRCH.
2553 */
2554 if ((_res.options & (RES_DEFNAMES|RES_DNSRCH)) ==
2555 (RES_DEFNAMES|RES_DNSRCH))
2556 {
2557 if (_res.dnsrch[(int)rptr->re_srch])
2558 (void)strncat(hname, _res.dnsrch[(int)rptr->re_srch],
2559 sizeof(hname) - ++len -1);
2560 }
2561 else if (_res.options & RES_DEFNAMES)
2562 (void)strncat(hname, ar_domainname, sizeof(hname) - len -1);
2563 }
2564
2565 /*
2566 * Store the name passed as the one to lookup and generate other host
2567 * names to pass onto the nameserver(s) for lookups.
2568 */
2569 if (!rptr)
2570 {
2571 rptr = ar_make_request(resi, nick, user, h, chan, server, func, command);
2572 rptr->re_type = T_A;
2573 (void)strncpy(rptr->re_name, name, sizeof(rptr->re_name)-1);
2574 }
2575 return (ar_query_name(hname, C_IN, T_A, rptr));
2576 }
2577
2578 /*
2579 * ar_gethostbyaddr
2580 *
2581 * Generates a query for a given IP address.
2582 */
ar_gethostbyaddr(char * addr,char * info,int size,char * nick,char * user,char * h,char * chan,int server,void (* func)(),char * command)2583 int ar_gethostbyaddr(char *addr, char *info, int size, char *nick, char *user, char *h, char *chan, int server, void (*func)(), char *command)
2584 {
2585 struct resinfo resi;
2586 register struct resinfo *rp = &resi;
2587
2588 if (size && info)
2589 {
2590 rp->ri_ptr = (char *)new_malloc(size+1);
2591 if (*info)
2592 bcopy(info, rp->ri_ptr, size);
2593 rp->ri_size = size;
2594 }
2595 else
2596 memset((char *)rp, 0, sizeof(resi));
2597 ar_reinfo.re_nu_look++;
2598 return (do_query_number(rp, addr, NULL, nick, user, h, chan, server, func, command));
2599 }
2600
2601 /*
2602 * do_query_number
2603 *
2604 * Use this to do reverse IP# lookups.
2605 */
do_query_number(struct resinfo * resi,char * numb,register struct reslist * rptr,char * nick,char * user,char * h,char * chan,int server,void (* func)(),char * command)2606 static int do_query_number(struct resinfo *resi, char *numb, register struct reslist *rptr, char *nick, char *user, char *h, char *chan, int server, void (*func)(), char *command)
2607 {
2608 register unsigned char *cp;
2609 static char ipbuf[32];
2610
2611 /*
2612 * Generate name in the "in-addr.arpa" domain. No addings bits to this
2613 * name to get more names to query!.
2614 */
2615 cp = (unsigned char *)numb;
2616 (void)sprintf(ipbuf,"%u.%u.%u.%u.in-addr.arpa.",
2617 (unsigned int)(cp[3]), (unsigned int)(cp[2]),
2618 (unsigned int)(cp[1]), (unsigned int)(cp[0]));
2619
2620 if (!rptr)
2621 {
2622 rptr = ar_make_request(resi, nick, user, h, chan, server, func, command);
2623 rptr->re_type = T_PTR;
2624 rptr->re_he.h_length = sizeof(struct in_addr);
2625 memcpy((char *)&rptr->re_addr, numb, rptr->re_he.h_length);
2626 memcpy((char *)&rptr->re_he.h_addr_list[0].s_addr, numb,
2627 rptr->re_he.h_length);
2628 }
2629 return (ar_query_name(ipbuf, C_IN, T_PTR, rptr));
2630 }
2631
2632 /*
2633 * ar_resent_query
2634 *
2635 * resends a query.
2636 */
ar_resend_query(struct reslist * rptr)2637 static int ar_resend_query(struct reslist *rptr)
2638 {
2639 if (!rptr->re_resend)
2640 return -1;
2641
2642 switch(rptr->re_type)
2643 {
2644 case T_PTR:
2645 ar_reinfo.re_resends++;
2646 return do_query_number(NULL, (char *)&rptr->re_addr, rptr, NULL, NULL, NULL, NULL, -1, NULL, NULL);
2647 case T_A:
2648 ar_reinfo.re_resends++;
2649 return do_query_name(NULL, rptr->re_name, rptr, NULL, NULL, NULL, NULL, -1, NULL, NULL);
2650 default:
2651 break;
2652 }
2653
2654 return -1;
2655 }
2656
2657 /*
2658 * ar_procanswer
2659 *
2660 * process an answer received from a nameserver.
2661 */
ar_procanswer(struct reslist * rptr,HEADER * hptr,char * buf,char * eob)2662 static int ar_procanswer(struct reslist *rptr, HEADER *hptr, char *buf, char *eob)
2663 {
2664 char *cp, **alias;
2665 int class, type, dlen, len, ans = 0, n;
2666 unsigned int ttl, dr, *adr;
2667 struct hent *hp;
2668
2669 cp = buf + HFIXEDSZ;
2670 adr = (unsigned int *)rptr->re_he.h_addr_list;
2671
2672 while (*adr)
2673 adr++;
2674
2675 alias = rptr->re_he.h_aliases;
2676 while (*alias)
2677 alias++;
2678
2679 hp = &rptr->re_he;
2680
2681
2682 /*
2683 * Skip over the original question.
2684 */
2685 #ifndef __QNX__
2686 /* QNX doesn't seem to have this function, not sure
2687 * what it does at the moment but I may change this
2688 * in the future. - Brian
2689 */
2690 while (hptr->qdcount-- > 0)
2691 cp += dn_skipname(cp, eob) + QFIXEDSZ;
2692 #endif
2693 /*
2694 * proccess each answer sent to us. blech.
2695 */
2696 while (hptr->ancount-- > 0 && cp < eob) {
2697 n = dn_expand(buf, eob, cp, ar_hostbuf, sizeof(ar_hostbuf)-1);
2698 cp += n;
2699 if (n <= 0)
2700 return ans;
2701
2702 ans++;
2703 /*
2704 * 'skip' past the general dns crap (ttl, class, etc) to get
2705 * the pointer to the right spot. Some of thse are actually
2706 * useful so its not a good idea to skip past in one big jump.
2707 */
2708 GETSHORT(type, cp);
2709 GETSHORT(class, cp);
2710 GETLONG(ttl, cp);
2711 GETSHORT(dlen, cp);
2712 rptr->re_type = type;
2713
2714 switch(type)
2715 {
2716 case T_A :
2717 if (dlen != sizeof(struct in_addr))
2718 return 0;
2719 rptr->re_he.h_length = dlen;
2720 if (ans == 1)
2721 rptr->re_he.h_addrtype=(class == C_IN) ?
2722 AF_INET : AF_UNSPEC;
2723 memcpy(&dr, cp, dlen);
2724 *adr++ = dr;
2725 *adr = 0;
2726 cp += dlen;
2727 len = strlen(ar_hostbuf);
2728 if (!rptr->re_he.h_name)
2729 malloc_strcpy(&rptr->re_he.h_name, ar_hostbuf);
2730 break;
2731 case T_PTR :
2732 if ((n = dn_expand(buf, eob, cp, ar_hostbuf,
2733 sizeof(ar_hostbuf)-1 )) < 0)
2734 {
2735 cp += n;
2736 continue;
2737 }
2738 ar_hostbuf[HOSTLEN] = 0;
2739 cp += n;
2740 len = strlen(ar_hostbuf)+1;
2741 /*
2742 * copy the returned hostname into the host name
2743 * or alias field if there is a known hostname
2744 * already.
2745 */
2746 if (!rptr->re_he.h_name)
2747 malloc_strcpy(&rptr->re_he.h_name, ar_hostbuf);
2748 else
2749 {
2750 *alias = (char *)new_malloc(len);
2751 strcpy(*alias++, ar_hostbuf);
2752 *alias = NULL;
2753 }
2754 break;
2755 case T_CNAME :
2756 cp += dlen;
2757 if (alias >= &(rptr->re_he.h_aliases[MAXALIASES-1]))
2758 continue;
2759 n = strlen(ar_hostbuf)+1;
2760 *alias = (char *)new_malloc(n);
2761 (void)strcpy(*alias++, ar_hostbuf);
2762 *alias = NULL;
2763 break;
2764 default :
2765 cp += dlen;
2766 break;
2767 }
2768 }
2769
2770 return ans;
2771 }
2772
2773 /*
2774 * ar_answer
2775 *
2776 * Get an answer from a DNS server and process it. If a query is found to
2777 * which no answer has been given to yet, copy its 'info' structure back
2778 * to where "reip" points and return a pointer to the hostent structure.
2779 */
ar_answer(char * reip,int size,void (* func)(struct reslist *))2780 struct hostent *ar_answer(char *reip, int size, void (*func)(struct reslist *) )
2781 {
2782 static char ar_rcvbuf[HFIXEDSZ + MAXPACKET];
2783 static struct hostent ar_host;
2784
2785 HEADER hptr;
2786 struct reslist *rptr = NULL;
2787 struct hostent *hp;
2788 char **s;
2789 unsigned long *adr;
2790 int rc, i, n, a;
2791
2792 rc = recv(ar_resfd, ar_rcvbuf, sizeof(ar_rcvbuf), 0);
2793 if (rc <= 0)
2794 goto getres_err;
2795
2796 ar_reinfo.re_replies++;
2797 /* hptr = (HEADER *)ar_rcvbuf;*/
2798 memcpy(&hptr, ar_rcvbuf, sizeof(HEADER));
2799
2800 /*
2801 * convert things to be in the right order.
2802 */
2803 hptr.id = ntohs(hptr.id);
2804 hptr.ancount = ntohs(hptr.ancount);
2805 hptr.arcount = ntohs(hptr.arcount);
2806 hptr.nscount = ntohs(hptr.nscount);
2807 hptr.qdcount = ntohs(hptr.qdcount);
2808 /*
2809 * response for an id which we have already received an answer for
2810 * just ignore this response.
2811 */
2812 rptr = ar_find_id(hptr.id);
2813 if (!rptr)
2814 goto getres_err;
2815
2816 if ((hptr.rcode != NOERROR) || (hptr.ancount == 0))
2817 {
2818 switch (hptr.rcode)
2819 {
2820 case NXDOMAIN:
2821 h_errno = HOST_NOT_FOUND;
2822 break;
2823 case SERVFAIL:
2824 h_errno = TRY_AGAIN;
2825 break;
2826 case NOERROR:
2827 h_errno = NO_DATA;
2828 break;
2829 case FORMERR:
2830 case NOTIMP:
2831 case REFUSED:
2832 default:
2833 h_errno = NO_RECOVERY;
2834 break;
2835 }
2836 ar_reinfo.re_errors++;
2837 /*
2838 ** If a bad error was returned, we stop here and dont send
2839 ** send any more (no retries granted).
2840 */
2841 if (h_errno != TRY_AGAIN)
2842 {
2843 rptr->re_resend = 0;
2844 rptr->re_retries = 0;
2845 }
2846 goto getres_err;
2847 }
2848
2849 a = ar_procanswer(rptr, &hptr, ar_rcvbuf, ar_rcvbuf+rc);
2850
2851 if ((rptr->re_type == T_PTR) && (_res.options & RES_CHECKPTR))
2852 {
2853 /*
2854 * For reverse lookups on IP#'s, lookup the name that is given
2855 * for the ip# and return with that as the official result.
2856 * -avalon
2857 */
2858 rptr->re_type = T_A;
2859 /*
2860 * Clean out the list of addresses already set, even though
2861 * there should only be one :)
2862 */
2863 adr = (unsigned long *)rptr->re_he.h_addr_list;
2864 while (*adr)
2865 *adr++ = 0L;
2866 /*
2867 * Lookup the name that we were given for the ip#
2868 */
2869 ar_reinfo.re_na_look++;
2870 (void)strncpy(rptr->re_name, rptr->re_he.h_name,
2871 sizeof(rptr->re_name)-1);
2872 rptr->re_he.h_name = NULL;
2873 rptr->re_retries = MAX_RETRIES;/*_res.retry + 2;*/
2874 rptr->re_sends = 1;
2875 rptr->re_resend = 1;
2876 if (rptr->re_he.h_name)
2877 new_free(&rptr->re_he.h_name);
2878 ar_reinfo.re_na_look++;
2879 (void)ar_query_name(rptr->re_name, C_IN, T_A, rptr);
2880 return NULL;
2881 }
2882
2883 if (reip && rptr->re_rinfo.ri_ptr && size)
2884 memcpy(reip, rptr->re_rinfo.ri_ptr,
2885 MIN(rptr->re_rinfo.ri_size, size));
2886
2887 /*
2888 * Clean up structure from previous usage.
2889 */
2890 hp = &ar_host;
2891 if (hp->h_name)
2892 new_free(&hp->h_name);
2893 if ((s = hp->h_aliases))
2894 {
2895 while (*s)
2896 {
2897 new_free(s);
2898 s++;
2899 }
2900 new_free(&hp->h_aliases);
2901 }
2902 if ((s = hp->h_addr_list))
2903 {
2904
2905 while (*s)
2906 {
2907 new_free(s);
2908 s++;
2909 }
2910 new_free(&hp->h_addr_list);
2911 hp->h_addr_list = NULL;
2912 }
2913 memset ((char *)hp, 0, sizeof(*hp));
2914 /*
2915 * Setup and copy details for the structure we return a pointer to.
2916 */
2917 hp->h_addrtype = AF_INET;
2918 hp->h_length = sizeof(struct in_addr);
2919 malloc_strcpy(&hp->h_name, rptr->re_he.h_name);
2920 /*
2921 * Count IP#'s.
2922 */
2923 for (i = 0, n = 0; i < MAXADDRS; i++, n++)
2924 if (!rptr->re_he.h_addr_list[i].s_addr)
2925 break;
2926 s = hp->h_addr_list = (char **)new_malloc((n + 1) * sizeof(char *));
2927 if (n)
2928 {
2929 *s = (char *)new_malloc(sizeof(struct in_addr));
2930 memcpy(*s, (char *)&rptr->re_he.h_addr_list[0].s_addr,
2931 sizeof(struct in_addr));
2932 s++;
2933 for (i = 1; i < n; i++, s++)
2934 {
2935 *s = (char *)new_malloc(sizeof(struct in_addr));
2936 memcpy(*s, (char *)&rptr->re_he.h_addr_list[i].s_addr,
2937 sizeof(struct in_addr));
2938 }
2939 }
2940 *s = NULL;
2941 /*
2942 * Count CNAMEs
2943 */
2944 for (i = 0, n = 0; i < MAXADDRS; i++, n++)
2945 if (!rptr->re_he.h_aliases[i])
2946 break;
2947 s = hp->h_aliases = (char **)new_malloc((n + 1) * sizeof(char *));
2948 for (i = 0; i < n; i++)
2949 {
2950 *s++ = rptr->re_he.h_aliases[i];
2951 rptr->re_he.h_aliases[i] = NULL;
2952 }
2953 *s = NULL;
2954 if (rptr->func)
2955 (*rptr->func)(rptr);
2956 else if (func)
2957 (*func)(rptr);
2958 if (a > 0)
2959 (void)ar_remrequest(rptr);
2960 else
2961 if (!rptr->re_sent)
2962 (void)ar_remrequest(rptr);
2963 return hp;
2964
2965 getres_err:
2966 if (rptr)
2967 {
2968 if (reip && rptr->re_rinfo.ri_ptr && size)
2969 memcpy(reip, rptr->re_rinfo.ri_ptr,
2970 MIN(rptr->re_rinfo.ri_size, size));
2971 if ((h_errno != TRY_AGAIN) &&
2972 ((_res.options & (RES_DNSRCH|RES_DEFNAMES)) ==
2973 (RES_DNSRCH|RES_DEFNAMES) ))
2974 if (_res.dnsrch[(int)rptr->re_srch])
2975 {
2976 rptr->re_retries = MAX_RETRIES; /*_res.retry + 2;*/
2977 rptr->re_sends = 1;
2978 rptr->re_resend = 1;
2979 (void)ar_resend_query(rptr);
2980 rptr->re_srch++;
2981 }
2982 return NULL;
2983 }
2984 return NULL;
2985 }
2986
2987 static int ar_seq = 0;
2988 static int ar_lookup = 0;
2989
2990 #endif /* THREAD */
2991 #endif /* WANT_NSLOOKUP */
2992
set_nslookupfd(fd_set * rd)2993 void set_nslookupfd(fd_set *rd)
2994 {
2995 #ifdef WANT_NSLOOKUP
2996 #ifdef THREAD
2997 set_dns_output_fd(rd);
2998 #else
2999 int s;
3000 if ((s = ar_init(0)) != -1)
3001 FD_SET(s, rd);
3002 #endif /* THREAD */
3003 #endif /* WANT_NSLOOKUP */
3004 }
3005
print_nslookup(fd_set * rd)3006 long print_nslookup(fd_set *rd)
3007 {
3008 #ifdef WANT_NSLOOKUP
3009 #ifdef THREAD
3010 dns_check(rd);
3011 #else
3012 struct hostent *hp = NULL;
3013 int ar_del = 0;
3014 int s;
3015 if ((s = ar_init(0)) == -1)
3016 return -1;
3017 if (!(FD_ISSET(s, rd)))
3018 {
3019 unsigned long when = 0;
3020 when = ar_timeout(now, (char *)&ar_del, sizeof(ar_del), print_ns_fail);
3021 if (ar_del)
3022 ar_lookup--;
3023 return when;
3024 }
3025 if ((hp = ar_answer((char *)&ar_del, sizeof(ar_del), print_ns_succede)))
3026 {
3027 char **s;
3028 ar_lookup--;
3029 new_free(&hp->h_name);
3030 if ((s = hp->h_aliases))
3031 {
3032 while (*s)
3033 {
3034 new_free(s);
3035 s++;
3036 }
3037 new_free(&hp->h_aliases);
3038 }
3039 if ((s = hp->h_addr_list))
3040 {
3041 while (*s)
3042 {
3043 new_free(s);
3044 s++;
3045 }
3046 new_free(&hp->h_addr_list);
3047 }
3048 }
3049 #endif /* THREAD */
3050 #endif /* WANT_NSLOOKUP */
3051 return -1;
3052 }
3053
do_nslookup(char * host,char * nick,char * user,char * chan,int server,void (* func)(),char * command)3054 char *do_nslookup(char *host, char *nick, char *user, char *chan, int server, void (*func)(), char *command)
3055 {
3056 #ifdef WANT_NSLOOKUP
3057 #ifdef THREAD
3058 struct reslist *info = new_malloc(sizeof(struct reslist));
3059
3060 info->host = m_strdup(host);
3061 info->nick = m_strdup(nick);
3062 info->user = m_strdup(user);
3063 info->channel = m_strdup(chan);
3064 if(command)
3065 info->command = m_strdup(command);
3066 info->server = server;
3067 info->func = func;
3068
3069 add_to_dns_queue(host, cdns_generic_callback, NULL, info, DNS_URGENT);
3070 #else
3071 struct in_addr temp1;
3072
3073 if (!host)
3074 return NULL;
3075
3076 if ((ar_init(0) == -1))
3077 ar_init(ARES_INITLIST|ARES_INITSOCK|ARES_CALLINIT);
3078
3079 ar_lookup++;
3080 if (isdigit((unsigned char)*(host + strlen(host) - 1)))
3081 {
3082 ar_seq++;
3083 temp1.s_addr = inet_addr(host);
3084 ar_gethostbyaddr((char *)&temp1.s_addr, (char *)&ar_seq, sizeof(ar_seq), nick, user, host, chan, server, func, command);
3085 }
3086 else
3087 {
3088 ar_seq++;
3089 ar_gethostbyname(host, (char *)&ar_seq, sizeof(ar_seq), nick, user, host, chan, server, func, command);
3090 }
3091 #endif /* THREAD */
3092 #endif /* WANT_NSLOOKUP */
3093 return NULL;
3094 }
3095
3096 #ifdef WANT_NSLOOKUP
userhost_nsl(UserhostItem * stuff,char * nick,char * args)3097 void userhost_nsl(UserhostItem *stuff, char *nick, char *args)
3098 {
3099 char *nsl = NULL;
3100
3101 if (!stuff || !stuff->nick || !nick || !strcmp(stuff->user, "<UNKNOWN>") || my_stricmp(stuff->nick, nick))
3102 {
3103 say("No information for %s", nick);
3104 return;
3105 }
3106 if(args)
3107 {
3108 nsl = LOCAL_COPY(args);
3109 next_arg(nsl, &nsl);
3110 }
3111 nsl = do_nslookup(stuff->host, stuff->nick, stuff->user, NULL, from_server, NULL, (nsl && *nsl) ? nsl : NULL);
3112 }
3113 #endif
3114
BUILT_IN_COMMAND(nslookup)3115 BUILT_IN_COMMAND(nslookup)
3116 {
3117 #ifdef WANT_NSLOOKUP
3118 char *host,
3119 *hostname,
3120 *cmd = NULL;
3121 int count = 0;
3122 while ((host = next_arg(args, &args)))
3123 {
3124 if (count == 0)
3125 bitchsay("Checking tables...");
3126 if (*host == '-' || *host == '/')
3127 {
3128 host++;
3129
3130 if (host && !my_stricmp(host, "cmd"))
3131 {
3132 if (!(cmd = next_expr(&args, '{')))
3133 bitchsay("Need {...} for -CMD arguement");
3134 else
3135 host = next_arg(args, &args);
3136 }
3137 }
3138 if (!host || !*host)
3139 break;
3140 if (!strchr(host, '.'))
3141 userhostbase(host, userhost_nsl, 1, "%s%s%s", host, cmd ? space:empty_string, cmd?cmd:empty_string);
3142 else
3143 hostname = do_nslookup(host, NULL, NULL, NULL, from_server, NULL, cmd ? cmd : NULL);
3144 count++;
3145 }
3146 #else
3147 put_it("This command is disabled in this client");
3148 #endif
3149 }
3150
3151
rights(char * string,int num)3152 char *rights(char *string, int num)
3153 {
3154 if (strlen(string) < num)
3155 return string;
3156 return (string + strlen(string) - num);
3157 }
3158
numchar(char * string,char c)3159 int numchar(char *string, char c)
3160 {
3161 int num = 0;
3162
3163 while (*string)
3164 {
3165 if (tolower(*string) == tolower(c))
3166 num++;
3167 string++;
3168 }
3169 return num;
3170 }
3171
cluster(char * hostname)3172 char *cluster (char *hostname)
3173 {
3174 static char result[IRCD_BUFFER_SIZE/4 + 1];
3175 char temphost[BIG_BUFFER_SIZE + 1];
3176 char *host;
3177 char *atsign;
3178
3179 if (!hostname)
3180 return NULL;
3181
3182 *result = 0;
3183 atsign = strchr(hostname, '@');
3184 if (atsign) {
3185 if (*hostname == '~') {
3186 strcpy(result, "~*@");
3187 } else {
3188 size_t ident_len = atsign - hostname;
3189
3190 if (ident_len <= 9) {
3191 /* copy ident@ */
3192 strncat(result, hostname, ident_len + 1);
3193 } else {
3194 strncat(result, hostname, 8);
3195 strcat(result, "*@");
3196 }
3197 }
3198 hostname = atsign + 1;
3199 }
3200
3201 strlcpy(temphost, hostname, sizeof temphost);
3202 host = temphost;
3203
3204 if (*host && isdigit((unsigned char)*(host + strlen(host) - 1)))
3205 {
3206 /* Thanks icebreak for this small patch which fixes this function */
3207 int i;
3208 char *tmp;
3209 char count = 0;
3210
3211 tmp = host;
3212 while((tmp - host) < strlen(host))
3213 {
3214 if((tmp = strchr(tmp,'.')) == NULL)
3215 break;
3216 count++;
3217 tmp++;
3218 }
3219 tmp = host;
3220 for (i = 0; i < count; i++)
3221 tmp = strchr(tmp, '.') + 1;
3222 *tmp = '\0';
3223 strlcat(result, host, sizeof result);
3224 strlcat(result, "*", sizeof result);
3225 }
3226 else
3227 {
3228 char *tmp;
3229 int num;
3230
3231 num = 1;
3232 tmp = rights(host, 3);
3233 if (my_stricmp(tmp, "com") &&
3234 my_stricmp(tmp, "edu") &&
3235 my_stricmp(tmp, "net") &&
3236 (stristr(host, "com") ||
3237 stristr(host, "edu")))
3238 num = 2;
3239 while (host && *host && (numchar(host, '.') > num))
3240 {
3241 if ((host = strchr(host, '.')) != NULL)
3242 host++;
3243 else
3244 return (char *) NULL;
3245 }
3246
3247 /* We don't need strlcat for these first two, because
3248 * at this point the maximum length of the string in
3249 * result is 11 */
3250 strcat(result, "*");
3251 if (my_stricmp(host, temphost))
3252 strcat(result, ".");
3253 strlcat(result, host, sizeof result);
3254 }
3255 return result;
3256 }
3257
3258
3259
3260
3261 struct _sock_manager
3262 {
3263 int init;
3264 int count;
3265 int max_fd;
3266 SocketList sockets[FD_SETSIZE];
3267 } sock_manager = {0, 0, -1, {{ 0, 0, 0, NULL, 0, 0, NULL, NULL, NULL }}};
3268
3269 #define SOCKET_TIMEOUT 120
3270
3271
3272 #ifdef GUI
checkmenu(MenuList * check,int menuid)3273 char *checkmenu(MenuList *check, int menuid)
3274 {
3275 MenuList *tmpml;
3276 MenuStruct *tmpms;
3277 char *tmpalias;
3278
3279 tmpml=check;
3280 while(tmpml!=NULL)
3281 {
3282 if (tmpml->menutype==GUISUBMENU || tmpml->menutype==GUISHARED || tmpml->menutype==GUIBRKSUBMENU)
3283 {
3284 tmpms = (MenuStruct *)findmenu(tmpml->submenu);
3285 if ((tmpalias=checkmenu(tmpms->menuorigin, menuid))!=NULL)
3286 return tmpalias;
3287 }
3288 if (tmpml->menuid==menuid)
3289 return tmpml->alias;
3290 tmpml=tmpml->next;
3291 }
3292 return NULL;
3293 }
3294
scan_gui(fd_set * rd)3295 void scan_gui(fd_set *rd)
3296 {
3297 unsigned int guicmd[2];
3298 extern MenuStruct *morigin;
3299 extern unsigned long menucmd;
3300 extern char *codeptr, *paramptr;
3301 MenuStruct *tmpms;
3302 int newpos, cursb;
3303 char *alias;
3304 Window *scrollwin, *newfocuswindow;
3305 float bleah;
3306 Screen *newfocusscreen;
3307
3308 #ifdef __EMXPM__
3309 extern int just_resized;
3310 extern Screen *just_resized_screen;
3311
3312 if(just_resized == 1)
3313 WinSendMsg(just_resized_screen->hwndFrame, 0x041e, 0, 0);
3314 #endif
3315
3316 /* Read the data from the pipe and decide what to do */
3317 if(FD_ISSET(guiipc[0], rd))
3318 {
3319 read(guiipc[0], (void *)guicmd, sizeof(unsigned int) * 2);
3320 switch(guicmd[0])
3321 {
3322 case EVMENU:
3323 tmpms = morigin;
3324 while(tmpms!=NULL)
3325 {
3326 if((alias=checkmenu(tmpms->menuorigin, menucmd))!=NULL)
3327 {
3328 int save_server = from_server;
3329 Window *this_window = get_window_by_refnum((int)guicmd[1]);
3330
3331 if(this_window)
3332 from_server = this_window->server;
3333 make_window_current(this_window);
3334 parse_line(NULL, alias, empty_string, 0, 0, 1);
3335
3336 from_server = save_server;
3337 break;
3338 }
3339 tmpms=tmpms->next;
3340 }
3341 break;
3342 case EVFOCUS:
3343 gui_flush();
3344 newfocuswindow=get_window_by_refnum((int)guicmd[1]);
3345 if(newfocuswindow)
3346 newfocusscreen=newfocuswindow->screen;
3347 else
3348 newfocusscreen=NULL;
3349 if (newfocusscreen && newfocusscreen->current_window)
3350 {
3351 make_window_current(newfocusscreen->current_window);
3352 output_screen=last_input_screen=newfocusscreen;
3353 reset_display_target();
3354 set_input_prompt(current_window, get_string_var(INPUT_PROMPT_VAR), 1);
3355 }
3356 update_input(UPDATE_ALL);
3357 break;
3358 case EVTITLE:
3359 xterm_settitle();
3360 break;
3361 case EVREFRESH:
3362 refresh_window_screen(get_window_by_refnum((int)guicmd[1]));
3363 break;
3364 case EVSTRACK:
3365 if(newscrollerpos != lastscrollerpos || lastscrollerwindow != (int)guicmd[1])
3366 {
3367 lastscrollerpos=newscrollerpos;
3368 lastscrollerwindow=(int)guicmd[1];
3369 scrollwin=get_window_by_refnum((int)guicmd[1]);
3370 bleah = get_int_var(SCROLLBACK_VAR);
3371 newpos = (int)(((bleah-newscrollerpos) / bleah) * (scrollwin->display_buffer_size - scrollwin->display_size)) + scrollwin->display_size;
3372 cursb = scrollwin->distance_from_display;
3373 if (newpos > cursb)
3374 scrollback_backwards_lines(newpos-cursb);
3375 if (newpos < cursb)
3376 scrollback_forwards_lines(cursb-newpos);
3377 }
3378 break;
3379 case EVSUP:
3380 scrollback_backwards_lines(1);
3381 break;
3382 case EVSDOWN:
3383 scrollback_forwards_lines(1);
3384 break;
3385 case EVSUPPG:
3386 scrollback_backwards((char)NULL, NULL);
3387 break;
3388 case EVSDOWNPG:
3389 scrollback_forwards((char)NULL, NULL);
3390 break;
3391 case EVKEY:
3392 {
3393 int old_server = from_server;
3394
3395 if(current_window)
3396 from_server = current_window->server;
3397
3398 wm_process((int)guicmd[1]);
3399
3400 from_server = old_server;
3401 }
3402 break;
3403 case EVFILE:
3404 if(codeptr && *codeptr && paramptr)
3405 {
3406 make_window_current(get_window_by_refnum((int)guicmd[1]));
3407 parse_line(NULL, codeptr, paramptr, 0, 0, 1);
3408 new_free(&codeptr);
3409 new_free(¶mptr);
3410 }
3411 break;
3412 #ifdef GTK
3413 case EVPASTE:
3414 gtk_main_paste((int)guicmd[1]);
3415 break;
3416 case EVDELETE:
3417 scrollwin=get_window_by_refnum((int)guicmd[1]);
3418 if(scrollwin && scrollwin->screen)
3419 kill_screen(scrollwin->screen);
3420 break;
3421 #endif
3422 }
3423 }
3424 }
3425 #endif
3426
read_clonelist(int s)3427 void read_clonelist(int s)
3428 {
3429 char buffer[IRCD_BUFFER_SIZE + 1];
3430 char *str = buffer;
3431 switch(dgets(str, s, 0, IRCD_BUFFER_SIZE, NULL))
3432 {
3433 case -1:
3434 {
3435 do_hook(SOCKET_LIST, "%d %s %d", s, sock_manager.sockets[s].server, sock_manager.sockets[s].port);
3436 close_socketread(s);
3437 break;
3438 }
3439 case 0:
3440 break;
3441 default:
3442 {
3443 if ((buffer[strlen(buffer)-1] == '\r') || (buffer[strlen(buffer)-1] == '\n'))
3444 buffer[strlen(buffer)-1] = 0;
3445 if ((buffer[strlen(buffer)-1] == '\r') || (buffer[strlen(buffer)-1] == '\n'))
3446 buffer[strlen(buffer)-1] = 0;
3447 if (*buffer)
3448 do_hook(SOCKET_LIST, "%d %s %d %s", s, sock_manager.sockets[s].server, sock_manager.sockets[s].port, buffer);
3449 }
3450 }
3451 }
3452
read_clonenotify(int s)3453 void read_clonenotify(int s)
3454 {
3455 unsigned long flags = 0;
3456 flags = get_socketflags(s);
3457 do_hook(SOCKET_NOTIFY_LIST, "%d %s %d %d", s, sock_manager.sockets[s].server, sock_manager.sockets[s].port, (unsigned int)flags);
3458 }
3459
BX_set_socketflags(int s,unsigned long flags)3460 unsigned long BX_set_socketflags(int s, unsigned long flags)
3461 {
3462 if (check_socket(s))
3463 {
3464 sock_manager.sockets[s].flags = flags;
3465 return sock_manager.sockets[s].flags;
3466 }
3467 return 0;
3468 }
3469
BX_get_socketflags(int s)3470 unsigned long BX_get_socketflags(int s)
3471 {
3472 if (check_socket(s))
3473 return sock_manager.sockets[s].flags;
3474 return 0;
3475 }
3476
get_socketserver(int s)3477 char *get_socketserver(int s)
3478 {
3479 if (check_socket(s))
3480 return sock_manager.sockets[s].server;
3481 return NULL;
3482 }
3483
BX_get_socketinfo(int s)3484 void *BX_get_socketinfo(int s)
3485 {
3486 if (check_socket(s))
3487 return sock_manager.sockets[s].info;
3488 return NULL;
3489 }
3490
BX_set_socketinfo(int s,void * info)3491 void BX_set_socketinfo(int s, void *info)
3492 {
3493 if (check_socket(s))
3494 sock_manager.sockets[s].info = info;
3495 }
3496
BX_get_max_fd(void)3497 int BX_get_max_fd(void)
3498 {
3499 return sock_manager.max_fd + 1;
3500 }
3501
BX_add_socketread(int s,int port,unsigned long flags,char * server,void (* func_read)(int),void (* func_write)(int))3502 int BX_add_socketread(int s, int port, unsigned long flags, char *server, void (*func_read)(int), void (*func_write)(int))
3503 {
3504 if (!sock_manager.init)
3505 {
3506 fd_set rd;
3507 FD_ZERO(&rd);
3508 set_socket_read(&rd, &rd);
3509 }
3510 if (s >= FD_SETSIZE)
3511 {
3512 yell("File descriptor limit reached, dropping new socket.");
3513 close(s);
3514 return -1;
3515 }
3516 if (s > sock_manager.max_fd)
3517 sock_manager.max_fd = s;
3518 sock_manager.count++;
3519 sock_manager.sockets[s].is_read = s;
3520 sock_manager.sockets[s].port = port;
3521 sock_manager.sockets[s].flags = flags;
3522 if (server)
3523 sock_manager.sockets[s].server = m_strdup(server);
3524 sock_manager.sockets[s].func_read = func_read;
3525 sock_manager.sockets[s].func_write = func_write;
3526 new_open(s);
3527 return s;
3528 }
3529
BX_set_socketwrite(int s)3530 int BX_set_socketwrite(int s)
3531 {
3532 if (s >= FD_SETSIZE)
3533 return -1;
3534 if (s > sock_manager.max_fd)
3535 sock_manager.max_fd = s;
3536 sock_manager.sockets[s].is_write = s;
3537 new_open_write(s);
3538 return s;
3539 }
3540
BX_add_sockettimeout(int s,time_t timeout,void * func)3541 void BX_add_sockettimeout(int s, time_t timeout, void *func)
3542 {
3543 if (timeout < 0)
3544 {
3545 timeout = get_int_var(CONNECT_TIMEOUT_VAR);
3546 if (timeout <= 0)
3547 timeout = SOCKET_TIMEOUT;
3548 }
3549 if (timeout)
3550 sock_manager.sockets[s].time = now + timeout;
3551 else
3552 sock_manager.sockets[s].time = 0;
3553 sock_manager.sockets[s].cleanup = func;
3554 }
3555
BX_close_socketread(int s)3556 void BX_close_socketread(int s)
3557 {
3558 if (!sock_manager.count)
3559 return;
3560 if (sock_manager.sockets[s].is_read)
3561 {
3562 new_free(&sock_manager.sockets[s].server);
3563 if (sock_manager.sockets[s].is_write)
3564 new_close_write(s);
3565 new_close(s);
3566 memset(&sock_manager.sockets[s], 0, sizeof(SocketList));
3567 sock_manager.count--;
3568 if (s == sock_manager.max_fd)
3569 {
3570 int i;
3571 sock_manager.max_fd = -1;
3572 for (i = 0; i < FD_SETSIZE; i++)
3573 if (sock_manager.sockets[i].is_read)
3574 sock_manager.max_fd = i;
3575 else if( sock_manager.sockets[i].is_write)
3576 sock_manager.max_fd = i;
3577 }
3578 }
3579 }
3580
BX_check_socket(int s)3581 int BX_check_socket(int s)
3582 {
3583 if (s != -1 && sock_manager.count && sock_manager.sockets[s].is_read)
3584 return 1;
3585 return 0;
3586 }
3587
check_dcc_socket(int s)3588 int check_dcc_socket(int s)
3589 {
3590 if (sock_manager.count && sock_manager.sockets[s].is_read && sock_manager.sockets[s].info)
3591 {
3592 if ( ((dcc_struct_type *)sock_manager.sockets[s].info)->struct_type == DCC_STRUCT_TYPE)
3593 return 1;
3594 }
3595 return 0;
3596 }
3597
BX_write_sockets(int s,unsigned char * str,int len,int nl)3598 int BX_write_sockets(int s, unsigned char *str, int len, int nl)
3599 {
3600 if (s < 1)
3601 return -1;
3602 if (nl)
3603 {
3604 unsigned char *buf;
3605 buf = alloca(strlen(str)+4);
3606 strcpy(buf, str);
3607 strcat(buf, "\r\n");
3608 len += 2;
3609 return write(s, buf, len);
3610 }
3611 return write(s, str, len);
3612 }
3613
BX_read_sockets(int s,unsigned char * str,int len)3614 int BX_read_sockets(int s, unsigned char *str, int len)
3615 {
3616 if (s < 1)
3617 return -1;
3618 return read(s, str, len);
3619 }
3620
set_socket_read(fd_set * rd,fd_set * wr)3621 void set_socket_read (fd_set *rd, fd_set *wr)
3622 {
3623 register int i;
3624 static int socket_init = 0;
3625 if (!socket_init)
3626 {
3627 memset(&sock_manager, 0, sizeof(sock_manager));
3628 socket_init++;
3629 sock_manager.init++;
3630 }
3631 if (!sock_manager.count) return;
3632 for (i = 0; i < sock_manager.max_fd + 1; i++)
3633 {
3634 if (sock_manager.sockets[i].is_read)
3635 FD_SET(sock_manager.sockets[i].is_read, rd);
3636 if (sock_manager.sockets[i].is_write)
3637 FD_SET(sock_manager.sockets[i].is_write, wr);
3638 }
3639 }
3640
scan_sockets(fd_set * rd,fd_set * wr)3641 void scan_sockets(fd_set *rd, fd_set *wr)
3642 {
3643 register int i;
3644 time_t t = now;
3645 if (!sock_manager.count) return;
3646 for (i = 0; i < sock_manager.max_fd+1; i++)
3647 {
3648 if (sock_manager.sockets[i].is_read && FD_ISSET(sock_manager.sockets[i].is_read, rd))
3649 (sock_manager.sockets[i].func_read) (sock_manager.sockets[i].is_read);
3650 if (sock_manager.sockets[i].func_write && sock_manager.sockets[i].is_write && FD_ISSET(sock_manager.sockets[i].is_write, wr))
3651 (sock_manager.sockets[i].func_write) (sock_manager.sockets[i].is_write);
3652 if (sock_manager.sockets[i].time && (t >= sock_manager.sockets[i].time))
3653 {
3654 if (sock_manager.sockets[i].cleanup)
3655 (sock_manager.sockets[i].cleanup)(i);
3656 else
3657 close_socketread(i);
3658 }
3659 }
3660 }
3661
BX_get_socket(int s)3662 SocketList *BX_get_socket(int s)
3663 {
3664 if (check_socket(s))
3665 return &sock_manager.sockets[s];
3666 return NULL;
3667 }
3668
3669 extern int dgets_errno;
3670
read_netfinger(int s)3671 void read_netfinger(int s)
3672 {
3673 char tmpstr[BIG_BUFFER_SIZE+1];
3674 register unsigned char *p = tmpstr;
3675 *tmpstr = 0;
3676 switch(dgets(tmpstr, s, 0, BIG_BUFFER_SIZE, NULL))
3677 {
3678 case 0:
3679 break;
3680 case -1:
3681 if (do_hook(SOCKET_LIST, "%d %d %s Remote closed connection", s, sock_manager.sockets[s].port, sock_manager.sockets[s].server))
3682 {
3683 if (dgets_errno == -1)
3684 bitchsay("Remote closed connection");
3685 }
3686 close_socketread(s);
3687 break;
3688 default:
3689 {
3690 chop(tmpstr, 1);
3691 while (*p)
3692 {
3693 switch(*p)
3694 {
3695 case 0210:
3696 case 0211:
3697 case 0212:
3698 case 0214:
3699 *p -= 0200;
3700 break;
3701 case 0x9b:
3702 case '\t':
3703 break;
3704 case '\n':
3705 case '\r':
3706 *p = '\0';
3707 break;
3708 default:
3709 if (!isprint(*p))
3710 *p = (*p & 0x7f) | 0x40;
3711 break;
3712 }
3713 p++;
3714 }
3715 if (do_hook(SOCKET_LIST, "%d %d %s %s", s, sock_manager.sockets[s].port, sock_manager.sockets[s].server, tmpstr))
3716 put_it("%s", tmpstr);
3717 }
3718 }
3719 }
3720
netfinger(char * name)3721 void netfinger (char *name)
3722 {
3723 char *host = NULL;
3724 unsigned short port = 79;
3725 int s;
3726
3727 if (name)
3728 {
3729 if ((host = strrchr(name, '@')))
3730 *host++ = 0;
3731 else
3732 host = name;
3733 }
3734 if (!host || !*host)
3735 {
3736 say("Invalid @host or user@host.");
3737 return;
3738 }
3739
3740 if (name && *name)
3741 {
3742 if ((s = connect_by_number(host, &port, SERVICE_CLIENT, PROTOCOL_TCP, 1)) < 0)
3743 {
3744 bitchsay("Finger connect error on %s@%s", name?name:empty_string, host);
3745 return;
3746 }
3747 if ((add_socketread(s, port, 0, name, read_netfinger, NULL)) > -1)
3748 {
3749 write_sockets(s, name, strlen(name), 1);
3750 add_sockettimeout(s, 120, NULL);
3751 } else
3752 close_socketread(s);
3753 }
3754 return;
3755 }
3756
start_finger(UserhostItem * stuff,char * nick,char * args)3757 void start_finger (UserhostItem *stuff, char *nick, char *args)
3758 {
3759 char *finger_userhost = NULL;
3760 char *str;
3761 if (!stuff || !stuff->nick || !nick || !strcmp(stuff->user, "<UNKNOWN>") || my_stricmp(stuff->nick, nick))
3762 {
3763 say("No information for %s", nick);
3764 return;
3765 }
3766 finger_userhost = m_opendup(stuff->user, "@", stuff->host, NULL);
3767 str = finger_userhost;
3768 str = clear_server_flags(finger_userhost);
3769 say("Launching finger for %s (%s)", nick, finger_userhost);
3770 netfinger(str);
3771 new_free(&finger_userhost);
3772 }
3773
BUILT_IN_COMMAND(finger)3774 BUILT_IN_COMMAND(finger)
3775 {
3776 char *userhost;
3777
3778 if ((userhost = next_arg(args, &args)))
3779 {
3780 if (!strchr(userhost, '@'))
3781 {
3782 userhostbase(userhost, start_finger, 1, "%s", userhost);
3783 return;
3784 }
3785 netfinger(userhost);
3786 }
3787 }
3788
handle_socket_connect(int rc)3789 static void handle_socket_connect(int rc)
3790 {
3791 struct servent *serv;
3792 struct sockaddr_foobar addr;
3793 struct hostent *host;
3794 char buf[128], *hostname = buf;
3795 socklen_t address_len;
3796
3797 address_len = sizeof(struct sockaddr_foobar);
3798 if ((getpeername(rc, (struct sockaddr *) &addr, &address_len)) != -1)
3799 {
3800 serv = getservbyport(addr.sf_port,"tcp");
3801 strcpy(hostname, "unknown");
3802 if (addr.sf_family == AF_INET)
3803 {
3804 address_len = sizeof(struct in_addr);
3805 if ((host = gethostbyaddr((char *)&addr.sf_addr, address_len, AF_INET)))
3806 hostname = (char *)host->h_name;
3807 else
3808 hostname = inet_ntoa(addr.sf_addr);
3809 }
3810 #ifdef IPV6
3811 else
3812 {
3813 if (getnameinfo((struct sockaddr*) &addr, sizeof(struct sockaddr_foobar), hostname, 128, NULL, 0, 0))
3814 hostname = (char *)inet_ntop(AF_INET6, (void*) &(addr.sf_addr6), buf, 128);
3815 }
3816 #endif
3817 put_it("Hostname %s port %d is running (%s)", hostname, htons(addr.sf_port), serv == NULL? "UNKNOWN":serv->s_name);
3818 }
3819 close_socketread(rc);
3820 }
3821
scan(char * remote_host,int low_port,int high_port,struct sockaddr_foobar * host)3822 static int scan(char *remote_host, int low_port, int high_port, struct sockaddr_foobar *host)
3823 {
3824 unsigned short int port;
3825 int rc;
3826 if (low_port == 0) low_port = 1;
3827 for (port = low_port;port <= high_port;port++)
3828 {
3829 if ((rc = connect_by_number(remote_host, &port, SERVICE_CLIENT, PROTOCOL_TCP, 1)) < 0)
3830 continue;
3831 if ((add_socketread(rc, port, 0, NULL, handle_socket_connect, NULL)) > -1)
3832 add_sockettimeout(rc, 120, NULL);
3833 else
3834 close_socketread(rc);
3835 }
3836
3837 return 1;
3838 }
3839
userhost_scanport(UserhostItem * stuff,char * nick,char * args)3840 void userhost_scanport(UserhostItem *stuff, char *nick, char *args)
3841 {
3842 char *t;
3843 int low_port = 0,
3844 high_port = 0;
3845 struct sockaddr_foobar *host; /* gee, and what's this one for? */
3846
3847 if (!stuff || !stuff->nick || !nick || !strcmp(stuff->user, "<UNKNOWN>") || my_stricmp(stuff->nick, nick))
3848 {
3849 bitchsay("No such nick [%s] found", nick);
3850 return;
3851 }
3852 next_arg(args, &args);
3853 t = next_arg(args, &args);
3854 low_port = atol(t);
3855 t = next_arg(args, &args);
3856 high_port = atol(t);
3857 if ((host = resolv(stuff->host)))
3858 {
3859 bitchsay("Scanning %s ports %d to %d", stuff->host, low_port, high_port);
3860 scan(stuff->host, low_port, high_port, host);
3861 return;
3862 }
3863 bitchsay("Cannot resolv host %s for %s", stuff->host, stuff->nick);
3864 }
3865
BUILT_IN_COMMAND(findports)3866 BUILT_IN_COMMAND(findports)
3867 {
3868 char *remote_host;
3869 int low_port = 6660;
3870 int high_port = 7000;
3871 struct sockaddr_foobar *host;
3872
3873
3874 if (args && *args)
3875 {
3876 char *tmp = NULL;
3877 remote_host = next_arg(args, &args);
3878 if (args && *args)
3879 {
3880 tmp = next_arg(args, &args);
3881 low_port = strtoul(tmp, NULL, 10);
3882 if (args && *args)
3883 {
3884 tmp = next_arg(args, &args);
3885 high_port = strtoul(tmp, NULL, 10);
3886 }
3887 else
3888 high_port = low_port;
3889 }
3890 if (strchr(remote_host, '.') || strchr(remote_host, ':'))
3891 {
3892 if ((host = resolv(remote_host)))
3893 {
3894 bitchsay("Scanning %s's tcp ports %d through %d",remote_host, low_port,high_port);
3895 scan(remote_host, low_port, high_port, host);
3896 } else
3897 bitchsay("No such host %s", remote_host);
3898 }
3899 else
3900 userhostbase(remote_host, userhost_scanport, 1, "%s %d %d", remote_host, low_port, high_port);
3901 }
3902 return;
3903 }
3904
userhost_ignore(UserhostItem * stuff,char * nick1,char * args)3905 void userhost_ignore (UserhostItem *stuff, char *nick1, char *args)
3906 {
3907 char *p, *arg;
3908 char *nick = NULL, *user = NULL, *host = NULL;
3909 int old_window_display;
3910 char ignorebuf[BIG_BUFFER_SIZE+1];
3911 Ignore *igptr, *igtmp;
3912 WhowasList *whowas;
3913
3914 arg = next_arg(args, &args);
3915 if (!stuff || !stuff->nick || !nick1 || !strcmp(stuff->user, "<UNKNOWN>") || my_stricmp(stuff->nick, nick1))
3916 {
3917 if ((whowas = check_whowas_nick_buffer(nick1, arg, 0)))
3918 {
3919 bitchsay("Using WhoWas info for %s of %s ", arg, nick1);
3920 user = host; host = strchr(host, '@'); *host++ = 0;
3921 nick = whowas->nicklist->nick;
3922 }
3923 else
3924 {
3925 say("No match for user %s", nick1);
3926 return;
3927 }
3928 }
3929 else
3930 {
3931 user = clear_server_flags(stuff->user);
3932 host = stuff->host; nick = stuff->nick;
3933 }
3934 if (!arg || !*arg || !my_stricmp(arg, "+HOST"))
3935 sprintf(ignorebuf, "*!*@%s ALL -CRAP -PUBLIC", cluster(host));
3936 else if (!my_stricmp(arg, "+USER"))
3937 sprintf(ignorebuf, "*%s@%s ALL -CRAP -PUBLIC", user, cluster(host));
3938 else if (!my_stricmp(arg, "-USER") || !my_stricmp(arg, "-HOST"))
3939 {
3940 int found = 0;
3941 if (!my_stricmp(arg, "-HOST"))
3942 sprintf(ignorebuf, "*!*@%s", cluster(host));
3943 else
3944 sprintf(ignorebuf, "%s!%s@%s", nick, user, host);
3945 igptr = ignored_nicks;
3946 while (igptr != NULL)
3947 {
3948 igtmp = igptr->next;
3949 if (wild_match(igptr->nick, ignorebuf) ||
3950 wild_match(nick, igptr->nick))
3951 {
3952 sprintf(ignorebuf, "%s NONE", igptr->nick);
3953 old_window_display = window_display;
3954 window_display = 0;
3955 ignore(NULL, ignorebuf, ignorebuf, NULL);
3956 window_display = old_window_display;
3957 bitchsay("Unignored %s!%s@%s", nick, user, host);
3958 found++;
3959 }
3960 igptr = igtmp;
3961 }
3962 if (!found)
3963 bitchsay("No ignore matching %s found", nick);
3964 return;
3965 }
3966 old_window_display = window_display;
3967 window_display = 0;
3968 ignore(NULL, ignorebuf, ignorebuf, NULL);
3969 if ((arg = next_arg(args, &args)))
3970 {
3971 char tmp[BIG_BUFFER_SIZE+1];
3972 sprintf(tmp, "%s ^IGNORE %s NONE", arg, ignorebuf);
3973 timercmd("TIMER", tmp, NULL, NULL);
3974 }
3975 window_display = old_window_display;
3976 if ((p = strchr(ignorebuf, ' ')))
3977 *p = 0;
3978 say("Now ignoring ALL except CRAP and PUBLIC from %s", ignorebuf);
3979 return;
3980 }
3981
BUILT_IN_COMMAND(reset)3982 BUILT_IN_COMMAND(reset)
3983 {
3984 refresh_screen(0, NULL);
3985 }
3986
3987
3988 extern char *channel_key (char *);
BUILT_IN_COMMAND(cycle)3989 BUILT_IN_COMMAND(cycle)
3990 {
3991 char *to = NULL;
3992 int server = from_server;
3993 ChannelList *chan;
3994
3995 if (args && *args)
3996 to = make_channel(next_arg(args, &args));
3997
3998 if (!(chan = prepare_command(&server, to, NO_OP)))
3999 return;
4000 my_send_to_server(server, "PART %s\nJOIN %s%s%s", chan->channel, chan->channel, chan->key?space:empty_string, chan->key?chan->key:empty_string);
4001 }
4002
4003
do_newuser(char * command,char * args,char * subargs)4004 int do_newuser(char *command, char *args, char *subargs)
4005 {
4006 char *newusername = NULL;
4007 if ((newusername = next_arg(args, &args)))
4008 {
4009 #ifdef IDENT_FAKE
4010 FILE *outfile;
4011 char *p = NULL, *q = NULL;
4012 malloc_sprintf(&p, "~/%s", get_string_var(IDENT_HACK_VAR));
4013 q = expand_twiddle(p);
4014 if (!(outfile = fopen(q,"w")))
4015 return 0;
4016 #ifdef CIDENTD
4017 fprintf(outfile,"hideme\nmynameis %s\n", newusername);
4018 #else
4019 fprintf(outfile,"%s", newusername);
4020 #endif
4021 fclose(outfile);
4022 #endif
4023 strlcpy(username, newusername, sizeof username);
4024 if (subargs && *subargs)
4025 strlcpy(realname, subargs, sizeof realname);
4026 #ifdef IDENT_FAKE
4027 new_free(&p); new_free(&q);
4028 #endif
4029 reconnect_cmd(NULL, newusername, NULL, NULL);
4030 }
4031 else
4032 return 0;
4033 return 1;
4034 }
4035
BUILT_IN_COMMAND(newnick)4036 BUILT_IN_COMMAND(newnick)
4037 {
4038 char *newnick, *newusername;
4039
4040 if ((newnick = next_arg(args, &args)) &&
4041 (newusername = next_arg(args, &args)))
4042 do_newuser(newnick, newusername, args);
4043 else
4044 say("You must specify a nick and username");
4045 }
4046
4047
BUILT_IN_COMMAND(newuser)4048 BUILT_IN_COMMAND(newuser)
4049 {
4050 char *newusername;
4051
4052 if ((newusername = next_arg(args, &args)))
4053 {
4054 if ((do_newuser(NULL, newusername, args)))
4055 say("You must specify a username.");
4056 }
4057 }
4058
BUILT_IN_COMMAND(do_ig)4059 BUILT_IN_COMMAND(do_ig)
4060 {
4061 char *nick;
4062 char ignore_type[6];
4063 int got_ignore_type = 0;
4064 int need_time = 0;
4065 if (!args || !*args)
4066 goto bad_ignore;
4067
4068 while ((nick = next_arg(args, &args)))
4069 {
4070 if (!nick || !*nick)
4071 goto bad_ignore;
4072 if (*nick == '-' || *nick == '+')
4073 {
4074 if (!my_stricmp(nick, "-USER") || !my_stricmp(nick, "+HOST") || !my_stricmp(nick, "+USER") || !my_stricmp(nick, "-HOST"))
4075 strcpy(ignore_type, nick);
4076 if (!args || !*args)
4077 goto bad_ignore;
4078 got_ignore_type++;
4079 continue;
4080 }
4081 else if (!got_ignore_type)
4082 {
4083 if (command && !my_strnicmp(command, "IGH",3))
4084 strcpy(ignore_type, "+HOST");
4085 else if (command && !my_strnicmp(command, "IG",2))
4086 strcpy(ignore_type, "+USER");
4087 if (command && !my_strnicmp(command, "UNIGH", 5))
4088 strcpy(ignore_type, "-HOST");
4089 else if (command && !my_strnicmp(command, "UNIG", 4))
4090 strcpy(ignore_type, "-USER");
4091 if (command && toupper(command[strlen(command)-1]) == 'T')
4092 need_time ++;
4093 }
4094 if (need_time)
4095 userhostbase(nick, userhost_ignore, 1, "%s %d", ignore_type, get_int_var(IGNORE_TIME_VAR));
4096 else
4097 userhostbase(nick, userhost_ignore, 1, "%s", ignore_type);
4098 }
4099 bad_ignore:
4100 return;
4101 }
4102
put_user(const NickList * nick,const char * channel)4103 void put_user(const NickList *nick, const char *channel)
4104 {
4105 char *users_format;
4106
4107 if (nick->userlist)
4108 users_format = fget_string_var(FORMAT_USERS_USER_FSET);
4109 else if (nick->shitlist)
4110 users_format = fget_string_var(FORMAT_USERS_SHIT_FSET);
4111 else
4112 users_format = fget_string_var(FORMAT_USERS_FSET);
4113
4114 put_it("%s", convert_output_format(users_format, "%s %s %s %s %d %c",
4115 #ifdef WANT_USERLIST
4116 nick->userlist ? convert_flags(nick->userlist->flags) : nick->shitlist?ltoa(nick->shitlist->level):"n/a",
4117 #else
4118 "n/a",
4119 #endif
4120 channel, nick->nick,
4121 nick->host, nick->serverhops,
4122 nick_isop(nick) ? '@' : nick_isvoice(nick)? 'v' : ' '));
4123 }
4124
BUILT_IN_COMMAND(users)4125 BUILT_IN_COMMAND(users)
4126 {
4127 ChannelList *chan;
4128 NickList *nicks;
4129 NickList *sortl = NULL;
4130 char *to = NULL,
4131 *spec = "*!*@*",
4132 *temp1 = NULL;
4133 char modebuf[BIG_BUFFER_SIZE + 1];
4134 char msgbuf[BIG_BUFFER_SIZE +1];
4135 int count = 0,
4136 ops = 0,
4137 msg = 0,
4138 num_kicks = 0,
4139 hook = 0,
4140 not = 0,
4141 server = from_server,
4142 sorted = NICKSORT_NORMAL;
4143
4144 *msgbuf = 0;
4145 *modebuf = 0;
4146
4147 while (args && *args)
4148 {
4149 if (!args || !*args)
4150 break;
4151 temp1 = next_arg(args, &args);
4152 if (temp1 && *temp1 == '-')
4153 {
4154 if (!my_strnicmp(temp1, "-ops", strlen(temp1)))
4155 ops = 1;
4156 else if (!my_strnicmp(temp1, "-nonops", strlen(temp1)))
4157 ops = 2;
4158 else if (!my_strnicmp(temp1, "-msg", strlen(temp1)))
4159 msg = 1;
4160 else if (!my_strnicmp(temp1, "-notice", strlen(temp1)))
4161 msg = 2;
4162 else if (!my_strnicmp(temp1, "-nkill", strlen(temp1)))
4163 msg = 3;
4164 else if (!my_strnicmp(temp1, "-kill", strlen(temp1)))
4165 msg = 4;
4166 else if (!my_strnicmp(temp1, "-kick", strlen(temp1)))
4167 msg = 5;
4168 else if (!my_strnicmp(temp1, "-stats", strlen(temp1)))
4169 msg = 6;
4170 else if (!my_strnicmp(temp1, "-ips", strlen(temp1)))
4171 msg = 7;
4172 else if (!my_strnicmp(temp1, "-sort", strlen(temp1)) && args && *args)
4173 {
4174 if (!my_strnicmp(args, "none", 4))
4175 sorted = NICKSORT_NONE;
4176 else if (!my_strnicmp(args, "host", 4))
4177 sorted = NICKSORT_HOST;
4178 else if (!my_strnicmp(args, "nick", 4))
4179 sorted = NICKSORT_NICK;
4180 else if (!my_strnicmp(args, "ip", 3))
4181 sorted = NICKSORT_IP;
4182 else if (!my_strnicmp(args, "time", 3))
4183 sorted = NICKSORT_TIME;
4184 if (sorted != NICKSORT_NORMAL)
4185 next_arg(args, &args);
4186 }
4187 else if (strpbrk(temp1, "*!@."))
4188 {
4189 spec = temp1+1;
4190 not = 1;
4191 }
4192 }
4193 else if (temp1 && is_channel(temp1))
4194 to = temp1;
4195 else if (temp1 && strpbrk(temp1, "*!@."))
4196 spec = temp1;
4197 else
4198 {
4199 if (args && *args)
4200 temp1[strlen(temp1)] = ' ';
4201 args = temp1;
4202 break;
4203 }
4204 }
4205 if (!spec || !*spec)
4206 spec = "*!*@*";
4207 if (!(chan = prepare_command(&server, to, NO_OP)))
4208 {
4209 bitchsay(to?"Not on that channel %s":"No such channel %s", to?to:empty_string);
4210 return;
4211 }
4212 set_display_target(chan->channel, LOG_CRAP);
4213 if (command && !my_stricmp(command, "CHOPS"))
4214 ops = 1;
4215 if (command && !my_stricmp(command, "NOPS"))
4216 ops = 2;
4217
4218 if ((msg == 1 || msg == 2) && (!args || !*args))
4219 {
4220 say("No message given");
4221 reset_display_target();
4222 return;
4223 }
4224
4225 switch (msg)
4226 {
4227 case 6:
4228 if (do_hook(STAT_HEADER_LIST, "%s %s %s %s %s", "Nick", "dops", "kicks","nicks","publics"))
4229 put_it("Nick dops kicks nicks publics");
4230 break;
4231 case 0:
4232 {
4233 char *f;
4234 if ((f = fget_string_var(FORMAT_USERS_TITLE_FSET)))
4235 put_it("%s", convert_output_format(f, "%s %s", update_clock(GET_TIME), chan->channel));
4236 }
4237 default:
4238 break;
4239 }
4240
4241 sortl = sorted_nicklist(chan, sorted);
4242 for (nicks = sortl; nicks; nicks = nicks->next)
4243 {
4244 sprintf(modebuf, "%s!%s", nicks->nick,
4245 nicks->host ? nicks->host : "<UNKNOWN@UNKNOWN>");
4246 if (msg == 7 && nicks->ip)
4247 {
4248 strcat(modebuf, space);
4249 strcat(modebuf, nicks->ip);
4250 }
4251 if (((!not && wild_match(spec, modebuf)) || (not && !wild_match(spec, modebuf))) &&
4252 (!ops ||
4253 ((ops == 1) && nick_isop(nicks)) ||
4254 ((ops == 2) && !nick_isop(nicks)) ))
4255 {
4256 switch(msg)
4257 {
4258 case 3: /* nokill */
4259 count--;
4260 break;
4261 case 4: /* kill */
4262 {
4263 if (!isme(nicks->nick))
4264 my_send_to_server(server, "KILL %s :%s (%i", nicks->nick,
4265 args && *args ? args : get_reason(nicks->nick, NULL),
4266 count + 1);
4267 else
4268 count--;
4269 break;
4270 }
4271 case 5: /* mass kick */
4272 {
4273 if (!isme(nicks->nick))
4274 {
4275 if (*msgbuf)
4276 strcat(msgbuf, ",");
4277 strcat(msgbuf, nicks->nick);
4278 num_kicks++;
4279 } else
4280 count--;
4281 if ((get_int_var(NUM_KICKS_VAR) && (num_kicks == get_int_var(NUM_KICKS_VAR))) || strlen(msgbuf) >= 450)
4282 {
4283 my_send_to_server(server, "KICK %s %s :%s", chan->channel,
4284 msgbuf, (args && *args) ? args :
4285 "-=punt=-");
4286 *msgbuf = 0;
4287 num_kicks = 0;
4288 }
4289 break;
4290 }
4291 case 6:
4292 {
4293 if (!isme(nicks->nick))
4294 {
4295 if (do_hook(STAT_LIST, "%s %d %d %d %d", nicks->nick, nicks->dopcount, nicks->kickcount,
4296 nicks->nickcount, nicks->floodcount))
4297 put_it("%-10s %4d %4d %4d %4d",
4298 nicks->nick, nicks->dopcount, nicks->kickcount,
4299 nicks->nickcount, nicks->floodcount);
4300 }
4301 break;
4302 }
4303 case 7:
4304 if (do_hook(USERS_IP_LIST, "%s %s %s", nicks->nick, nicks->host, nicks->ip?nicks->ip:"Unknown"))
4305 put_it("%s!%s = %s", nicks->nick, nicks->host, nicks->ip?nicks->ip:"Unknown");
4306 break;
4307 case 1:
4308 case 2:
4309 {
4310 if (*msgbuf)
4311 strcat(msgbuf, ",");
4312 strcat(msgbuf, nicks->nick);
4313 if (strlen(msgbuf)+strlen(args) >= 490)
4314 {
4315 put_it("%s", convert_output_format(fget_string_var((msg == 1)?FORMAT_SEND_MSG_FSET:FORMAT_SEND_NOTICE_FSET), "%s %s %s %s", update_clock(GET_TIME),msgbuf, get_server_nickname(from_server), args));
4316 my_send_to_server(server, "%s %s :%s", (msg == 1) ? "PRIVMSG" : "NOTICE", msgbuf, args);
4317 *msgbuf = 0;
4318 }
4319 break;
4320 }
4321 default:
4322 {
4323 if (!count && do_hook(USERS_HEADER_LIST, "%s %s %s %s %s %s %s", "Level", "aop", "prot", "Channel", "Nick", "+o", "UserHost") && fget_string_var(FORMAT_USERS_HEADER_FSET))
4324 put_it("%s", convert_output_format(fget_string_var(FORMAT_USERS_HEADER_FSET), "%s", chan->channel));
4325
4326 if ((hook = do_hook(USERS_LIST, "%lu %s %s %s %d %c",
4327 nicks->userlist ? nicks->userlist->flags:nicks->shitlist?nicks->shitlist->level:0,
4328 chan->channel, nicks->nick,
4329 nicks->host, nicks->serverhops,
4330 nick_isop(nicks) ? '@' : nick_isvoice(nicks) ? 'v' :' ')))
4331 {
4332 put_user(nicks, chan->channel);
4333 }
4334 }
4335 }
4336 count++;
4337 }
4338 else if (msg == 3)
4339 {
4340 count++;
4341 if (!isme(nicks->nick))
4342 {
4343 my_send_to_server(server, "KILL %s :%s (%i", nicks->nick,
4344 args && *args ? args : get_reason(nicks->nick, NULL),
4345 count);
4346 }
4347 else
4348 count--;
4349 }
4350 }
4351 clear_sorted_nicklist(&sortl);
4352 if (!msg && do_hook(USERS_FOOTER_LIST, "%s", "End of Users"))
4353 ;
4354 else if (msg == 6 && do_hook(STAT_FOOTER_LIST, "%s", "End of stats"))
4355 ;
4356 else if (!count)
4357 {
4358 if (chan)
4359 {
4360 if (!command)
4361 say("No match of %s on %s", spec, chan->channel);
4362 else
4363 say("There are no [\002%s\002] on %s", command, chan->channel);
4364 }
4365 }
4366 else if (!msg && !hook)
4367 bitchsay("End of UserList on %s %d counted", chan->channel, count);
4368
4369 if (count && *msgbuf)
4370 {
4371 switch(msg)
4372 {
4373 case 1:
4374 case 2:
4375 {
4376 put_it("%s", convert_output_format(fget_string_var((msg == 1)?FORMAT_SEND_MSG_FSET:FORMAT_SEND_NOTICE_FSET), "%s %s %s %s", update_clock(GET_TIME),msgbuf, get_server_nickname(from_server), args));
4377 my_send_to_server(server, "%s %s :%s", (msg == 1) ? "PRIVMSG" : "NOTICE", msgbuf, args);
4378 break;
4379 }
4380 case 5:
4381 {
4382 if (chan)
4383 my_send_to_server(server, "KICK %s %s :%s", chan->channel,
4384 msgbuf, (args && *args) ? args : "-=punt=-");
4385 }
4386 default:
4387 break;
4388 }
4389 }
4390 reset_display_target();
4391
4392 }
4393
caps_fucknut(register unsigned char * crap)4394 int caps_fucknut (register unsigned char *crap)
4395 {
4396 int total = 0, allcaps = 0;
4397 /* removed from ComStud client */
4398 while (*crap)
4399 {
4400 if (isalpha(*crap))
4401 {
4402 total++;
4403 if (isupper(*crap))
4404 allcaps++;
4405 }
4406 crap++;
4407 }
4408 if (total > 12)
4409 {
4410 if ( ((unsigned int)(((float) allcaps / (float) total) * 100) >= 75))
4411 return (1);
4412 }
4413 return (0);
4414 }
4415
char_fucknut(register unsigned char * crap,char looking,int max)4416 int char_fucknut (register unsigned char *crap, char looking, int max)
4417 {
4418 int total = strlen(crap), allchar = 0;
4419
4420 while (*crap)
4421 {
4422 if ((*crap == looking))
4423 {
4424 crap++;
4425 while(*crap && *crap != looking)
4426 {
4427 allchar++;
4428 crap++;
4429 }
4430 }
4431 if (*crap)
4432 crap++;
4433 }
4434 if (total > 12)
4435 {
4436 if ( ((unsigned int)(((float) allchar / (float) total) * 100)) >= 75)
4437 return (1);
4438 }
4439 return (0);
4440 }
4441
4442
make_timestamp(int do_timestamp,char * timestr)4443 static char *make_timestamp(int do_timestamp, char *timestr)
4444 {
4445 static char time_str[61];
4446 if (do_timestamp && timestr)
4447 {
4448 struct tm timeval;
4449 *time_str = 0;
4450 timeval = *localtime(&now);
4451 strftime(time_str, 60, timestr, &timeval);
4452 return time_str;
4453 }
4454 return empty_string;
4455 }
4456
4457 static int cparse_recurse = -1;
4458 #ifndef BITCHX_LITE
4459 #define MAX_RECURSE 5
4460 #else
4461 #define MAX_RECURSE 3
4462 #endif
4463 #define RECURSE_CPARSE
4464
4465 /* One buffer for each recursive invocation. We also keep track of the
4466 * buffer size, so that it can be resized when necessary.
4467 */
4468 static char *cof_buffer[MAX_RECURSE + 1] = { NULL };
4469 static size_t cof_buffer_sz[MAX_RECURSE + 1 ] = { 0 };
4470 #define COF_BUFFER_HEADROOM 100
4471 #define COF_BUFFER_FREE(p) (cof_buffer[cparse_recurse] + cof_buffer_sz[cparse_recurse] - (p))
4472
convert_output_format_raw(const char * format,const char * str,va_list args)4473 char *convert_output_format_raw(const char *format, const char *str, va_list args)
4474 {
4475 char buffer2[5*BIG_BUFFER_SIZE+1];
4476 enum color_attributes this_color = BLACK;
4477 char *s;
4478 char *copy = NULL;
4479 char *tmpc = NULL;
4480 register char *p;
4481 int old_who_level = who_level;
4482 int bold = 0;
4483
4484 #ifdef WANT_CHELP
4485 extern int in_chelp;
4486 #endif
4487
4488 int arg_flags;
4489 char color_mod[] = "kbgcrmywKBGCRMYWn";
4490 char *c_mod = color_mod;
4491 int do_timestamp = get_int_var(TIMESTAMP_VAR);
4492 char *timestamp_str = get_string_var(TIMESTAMP_STRING_VAR);
4493
4494 if (!format)
4495 return empty_string;
4496 copy = LOCAL_COPY(format);
4497
4498
4499 cparse_recurse++;
4500
4501 if (cparse_recurse > MAX_RECURSE)
4502 {
4503 yell("cparse_recurse() recursed too many times! this should never happen!");
4504 return empty_string;
4505 }
4506
4507 *buffer2 = 0;
4508 if (str)
4509 {
4510 memset(buffer2, 0, sizeof buffer2);
4511 p = (char *)str;
4512 while(p && *p)
4513 {
4514 if (*p == '%')
4515 {
4516 switch(*++p)
4517 {
4518 case 's':
4519 {
4520 char *q, *s = (char *)va_arg(args, char *);
4521 #ifdef RECURSE_CPARSE
4522 char buff[(5 * BIG_BUFFER_SIZE)+1];
4523 q = buff;
4524 while (s && *s)
4525 {
4526 if (*s == '%')
4527 *q++ = '%';
4528 else if (*s == '$')
4529 *q++ = '$';
4530 *q++ = *s++;
4531 }
4532 *q = 0;
4533 if (*buff)
4534 strcat(buffer2, buff);
4535 #else
4536 if (s)
4537 strcat(buffer2, s);
4538 #endif
4539 break;
4540 }
4541 case 'd':
4542 {
4543 int d = (int) va_arg(args, int);
4544 strlcat(buffer2, ltoa((long)d), 5 * BIG_BUFFER_SIZE);
4545 break;
4546 }
4547 case 'c':
4548 {
4549 char c = (char )va_arg(args, int);
4550 #ifdef RECURSE_CPARSE
4551 if (c == '%')
4552 buffer2[strlen(buffer2)] = '%';
4553 else if (c == '$')
4554 buffer2[strlen(buffer2)] = '$';
4555 #endif
4556 buffer2[strlen(buffer2)] = c;
4557 break;
4558 }
4559 case 'u':
4560 {
4561 unsigned int d = (unsigned int) va_arg(args, unsigned int);
4562 strlcat(buffer2, ltoa(d), 5 * BIG_BUFFER_SIZE);
4563 break;
4564 }
4565 case 'l':
4566 {
4567 unsigned long d = (unsigned long) va_arg(args, unsigned long);
4568 strlcat(buffer2, ltoa(d), 5 * BIG_BUFFER_SIZE);
4569 break;
4570 }
4571 case '%':
4572 {
4573 buffer2[strlen(buffer2)] = '%';
4574 p++;
4575 break;
4576 }
4577 default:
4578 strlcat(buffer2, "%", 5 * BIG_BUFFER_SIZE);
4579 buffer2[strlen(buffer2)] = *p;
4580 }
4581 p++;
4582 }
4583 else
4584 {
4585 buffer2[strlen(buffer2)] = *p;
4586 p++;
4587 }
4588 }
4589 }
4590 else if (str)
4591 strlcpy(buffer2, str, 5 * BIG_BUFFER_SIZE);
4592
4593 if (!cof_buffer[cparse_recurse])
4594 {
4595 cof_buffer_sz[cparse_recurse] = BIG_BUFFER_SIZE;
4596 cof_buffer[cparse_recurse] = new_malloc(cof_buffer_sz[cparse_recurse]);
4597 }
4598
4599 s = cof_buffer[cparse_recurse];
4600 *s = 0;
4601
4602 tmpc = copy;
4603 if (!tmpc)
4604 goto done;
4605 while (*tmpc)
4606 {
4607 /* Ensure some headroom is available in the buffer */
4608 if (COF_BUFFER_FREE(s) < COF_BUFFER_HEADROOM)
4609 {
4610 size_t s_pos = s - cof_buffer[cparse_recurse];
4611
4612 cof_buffer_sz[cparse_recurse] += BIG_BUFFER_SIZE;
4613 RESIZE(cof_buffer[cparse_recurse], char, cof_buffer_sz[cparse_recurse]);
4614
4615 s = cof_buffer[cparse_recurse] + s_pos;
4616 }
4617
4618 if (*tmpc == '%')
4619 {
4620 char *cs;
4621 tmpc++;
4622 this_color = BLACK;
4623 if (*tmpc == '\0')
4624 {
4625 *s++ = '%';
4626 continue;
4627 }
4628 if (*tmpc == '%')
4629 {
4630 *s++ = *tmpc++;
4631 continue;
4632 }
4633 if (isdigit((unsigned char)*tmpc))
4634 {
4635 char background_mod[] = "01234567";
4636 char *blah = background_mod;
4637 if ((cs = strchr(background_mod, *tmpc)))
4638 {
4639 this_color = (cs - blah) + (bold ? BACK_BBLACK : BACK_BLACK);
4640 bold = 0;
4641 }
4642 else if (*tmpc == '8')
4643 {
4644 this_color = REVERSE_COLOR;
4645 bold = 0;
4646 }
4647 else
4648 {
4649 this_color = BOLD_COLOR;
4650 bold ^= 1;
4651 }
4652 }
4653 else if ((cs = strchr(color_mod, *tmpc)))
4654 this_color = (cs - c_mod);
4655 else if (*tmpc == 'F')
4656 this_color = BLINK_COLOR;
4657 else if (*tmpc == 'U')
4658 this_color = UNDERLINE_COLOR;
4659 else if (*tmpc == 'A')
4660 this_color = (int) (((float)UNDERLINE_COLOR * rand())/RAND_MAX);
4661 else if (*tmpc == 'P')
4662 this_color = MAGENTAB;
4663 else if (*tmpc == 'p')
4664 this_color = MAGENTA;
4665 else if (*tmpc == '@')
4666 {
4667 strlcpy(s, make_timestamp(do_timestamp, timestamp_str), COF_BUFFER_FREE(s));
4668 while(*s) s++;
4669 tmpc++;
4670 continue;
4671 }
4672 #if 1
4673 /* do we really wanna do this? */
4674 else if (*tmpc == '^') /* ibmpc charset */
4675 {
4676 strlcpy(s, "\033(U", COF_BUFFER_FREE(s));
4677 while(*s) s++;
4678 tmpc++;
4679 continue;
4680 }
4681 else if (*tmpc == '&') /* latin1 charset */
4682 {
4683 strlcpy(s, "\033(B", COF_BUFFER_FREE(s));
4684 while(*s) s++;
4685 tmpc++;
4686 continue;
4687 }
4688 else if (*tmpc == '$') /* custom charset */
4689 {
4690 strlcpy(s, "\033(K", COF_BUFFER_FREE(s));
4691 while(*s) s++;
4692 tmpc++;
4693 continue;
4694 }
4695 #endif
4696 else
4697 {
4698 *s++ = *tmpc;
4699 continue;
4700 }
4701 strlcpy(s, color_str[this_color], COF_BUFFER_FREE(s));
4702 while (*s) s++;
4703 tmpc++;
4704 continue;
4705 }
4706 else if (*tmpc == '$' && !in_chelp && cparse_recurse < MAX_RECURSE)
4707 {
4708 char *new_str = NULL;
4709 tmpc++;
4710 if (*tmpc == '\0')
4711 {
4712 *s++ = '$';
4713 continue;
4714 }
4715 if (*tmpc == '$')
4716 {
4717 *s++ = *tmpc++;
4718 continue;
4719 }
4720
4721 in_cparse++;
4722 tmpc = alias_special_char(&new_str, tmpc, buffer2, NULL, &arg_flags);
4723 in_cparse--;
4724
4725 if (new_str)
4726 {
4727 char *subformat;
4728 #ifdef RECURSE_CPARSE
4729 subformat = convert_output_format_raw((const char *)new_str, NULL, VA_NULL);
4730 #else
4731 subformat = new_str;
4732 #endif
4733 /* Ensure sufficient buffer space */
4734 if (COF_BUFFER_FREE(s) < strlen(subformat) + 1)
4735 {
4736 size_t s_pos = s - cof_buffer[cparse_recurse];
4737
4738 cof_buffer_sz[cparse_recurse] += BIG_BUFFER_SIZE + strlen(subformat);
4739 RESIZE(cof_buffer[cparse_recurse], char, cof_buffer_sz[cparse_recurse]);
4740
4741 s = cof_buffer[cparse_recurse] + s_pos;
4742 }
4743
4744 strlcpy(s, subformat, COF_BUFFER_FREE(s));
4745 new_free(&new_str);
4746 while (*s) { s++; }
4747 }
4748 if (!tmpc) break;
4749 continue;
4750 } else
4751 *s = *tmpc;
4752 tmpc++; s++;
4753 }
4754 *s = 0;
4755
4756 done:
4757 s = cof_buffer[cparse_recurse];
4758 who_level = old_who_level;
4759 cparse_recurse--;
4760
4761 return s;
4762 }
4763
BX_convert_output_format(const char * format,const char * str,...)4764 char *BX_convert_output_format(const char *format, const char *str, ...)
4765 {
4766 char *s;
4767 int old_alias_debug = alias_debug;
4768 va_list args;
4769
4770 alias_debug = 0;
4771 va_start(args, str);
4772 s = convert_output_format_raw(format, str, args);
4773 va_end(args);
4774 if (*s)
4775 strcat(s, color_str[NO_COLOR]);
4776 alias_debug = old_alias_debug;
4777 return s;
4778 }
4779
4780 #define RAW_BUFFER_SIZE (MAX_RECURSE * BIG_BUFFER_SIZE * 2)
convert_output_format2(const char * str)4781 char *convert_output_format2(const char *str)
4782 {
4783 unsigned char buffer[RAW_BUFFER_SIZE+1];
4784 unsigned char buffer2[RAW_BUFFER_SIZE+1];
4785 register unsigned char *s;
4786 char *copy = NULL;
4787 char *tmpc = NULL;
4788 int arg_flags;
4789
4790 if (!str)
4791 return m_strdup(empty_string);
4792
4793 memset(buffer, 0, BIG_BUFFER_SIZE);
4794 strlcpy(buffer2, str, RAW_BUFFER_SIZE);
4795 copy = tmpc = buffer2;
4796 s = buffer;
4797 while (*tmpc)
4798 {
4799 if (*tmpc == '$')
4800 {
4801 char *new_str = NULL;
4802 tmpc++;
4803 in_cparse++;
4804 tmpc = alias_special_char(&new_str, tmpc, copy, NULL, &arg_flags);
4805 in_cparse--;
4806 if (new_str)
4807 #ifdef RECURSE_CPARSE
4808 strlcat(s, convert_output_format(new_str, NULL, NULL), RAW_BUFFER_SIZE);
4809 #else
4810 strlcat(s, new_str, RAW_BUFFER_SIZE);
4811 #endif
4812 s = s + (strlen(new_str));
4813 new_free(&new_str);
4814 if (!tmpc) break;
4815 continue;
4816 } else
4817 *s = *tmpc;
4818 tmpc++; s++;
4819 }
4820 *s = 0;
4821 return m_strdup(buffer);
4822 }
4823
add_last_type(LastMsg * array,int size,char * from,char * uh,char * to,char * str)4824 void add_last_type (LastMsg *array, int size, char *from, char *uh, char *to, char *str)
4825 {
4826 int i;
4827 for (i = size - 1; i > 0; i--)
4828 {
4829
4830 malloc_strcpy(&array[i].last_msg, array[i - 1].last_msg);
4831 malloc_strcpy(&array[i].from, array[i - 1].from);
4832 malloc_strcpy(&array[i].uh, array[i - 1].uh);
4833 malloc_strcpy(&array[i].to, array[i - 1].to);
4834 malloc_strcpy(&array[i].time, array[i - 1].time);
4835 }
4836 malloc_strcpy(&array->last_msg, str);
4837 malloc_strcpy(&array->from, from);
4838 malloc_strcpy(&array->to, to);
4839 malloc_strcpy(&array->uh, uh);
4840 malloc_strcpy(&array->time, update_clock(GET_TIME));
4841 }
4842
check_last_type(LastMsg * array,int size,char * from,char * uh)4843 int check_last_type(LastMsg *array, int size, char *from, char *uh)
4844 {
4845 int i;
4846 for (i = 0; i < size-1; i++)
4847 {
4848 if (array[i].from && array[i].uh && !my_stricmp(from, array[i].from) && !my_stricmp(uh, array[i].uh))
4849 return 1;
4850 }
4851 return 0;
4852 }
4853
matchmcommand(char * origline,int count)4854 int matchmcommand(char *origline,int count)
4855 {
4856 int startnum=0;
4857 int endnum=0;
4858 char *tmpstr;
4859 char tmpbuf[IRCD_BUFFER_SIZE];
4860
4861 strncpy(tmpbuf,origline, IRCD_BUFFER_SIZE-1);
4862 tmpstr=tmpbuf;
4863 if (*tmpstr=='*') return(1);
4864 while (tmpstr && *tmpstr)
4865 {
4866 startnum=0;
4867 endnum=0;
4868 if (tmpstr && *tmpstr && *tmpstr=='-')
4869 {
4870 while (tmpstr && *tmpstr && !isdigit((unsigned char)*tmpstr))
4871 tmpstr++;
4872 endnum=atoi(tmpstr);
4873 startnum=1;
4874 while (tmpstr && *tmpstr && isdigit((unsigned char)*tmpstr))
4875 tmpstr++;
4876 }
4877 else
4878 {
4879 while (tmpstr && *tmpstr && !isdigit((unsigned char)*tmpstr))
4880 tmpstr++;
4881 startnum=atoi(tmpstr);
4882 while (tmpstr && *tmpstr && isdigit((unsigned char)*tmpstr))
4883 tmpstr++;
4884 if (tmpstr && *tmpstr && *tmpstr=='-') {
4885 while (tmpstr && *tmpstr && !isdigit((unsigned char)*tmpstr))
4886 tmpstr++;
4887 endnum=atoi(tmpstr);
4888 if (!endnum)
4889 endnum=1000;
4890 while (tmpstr && *tmpstr && isdigit((unsigned char)*tmpstr))
4891 tmpstr++;
4892 }
4893 }
4894 if (count==startnum || (count>=startnum && count<=endnum))
4895 return(1);
4896 }
4897 if (count==startnum || (count>=startnum && count<=endnum))
4898 return(1);
4899 return(0);
4900 }
4901
BX_prepare_command(int * active_server,char * channel,int flags)4902 ChannelList *BX_prepare_command(int *active_server, char *channel, int flags)
4903 {
4904 int server = 0;
4905 ChannelList *chan = NULL;
4906 int need_op;
4907
4908 if (!channel) {
4909 channel = get_current_channel_by_refnum(0);
4910
4911 if (!channel) {
4912 if (flags != PC_SILENT) {
4913 if (current_window)
4914 message_to(current_window->refnum);
4915 bitchsay("You're not on a channel!");
4916 message_to(0);
4917 }
4918 return NULL;
4919 }
4920 }
4921 server = current_window->server;
4922 *active_server = server;
4923 if (!(chan = lookup_channel(channel, server, 0)))
4924 {
4925 if (flags != PC_SILENT) {
4926 if (current_window)
4927 message_to(current_window->refnum);
4928 bitchsay("You're not on the channel: %s", channel);
4929 message_to(0);
4930 }
4931 return NULL;
4932 }
4933
4934 need_op = flags == NEED_OP || (flags == PC_TOPIC && (chan->mode & MODE_TOPIC));
4935 if (need_op && !chan->have_op && !chan->hop)
4936 {
4937 error_not_opped(chan->channel);
4938 return NULL;
4939 }
4940 return chan;
4941 }
4942
BX_make_channel(char * chan)4943 char *BX_make_channel (char *chan)
4944 {
4945 static char buffer[IRCD_BUFFER_SIZE+1];
4946 *buffer = 0;
4947 if (!chan)
4948 return NULL;
4949 if (*chan != '#' && *chan != '&' && *chan != '+' && *chan != '!')
4950 snprintf(buffer, IRCD_BUFFER_SIZE-2, "#%s", chan);
4951 else
4952 strlcpy(buffer, chan, sizeof buffer);
4953 return buffer;
4954 }
4955
4956
4957 extern int timed_server (void *, char *);
check_server_connect(int server)4958 void check_server_connect(int server)
4959 {
4960 #ifndef NON_BLOCKING_CONNECTS
4961 if (!get_int_var(AUTO_RECONNECT_VAR))
4962 return;
4963 if (server == -2)
4964 return;
4965 if ((server == -1) || (!get_server_in_timed(server) && get_server_lastmsg(server) + 50 < now))
4966 {
4967 if (!timer_callback_exists(timed_server))
4968 {
4969 add_timer(0, empty_string, 10 * 1000, 1, timed_server, m_strdup(ltoa(server)), NULL, current_window->refnum, "reconnect");
4970 set_server_in_timed(server, get_server_in_timed(server)+1);
4971 }
4972 }
4973 #endif
4974 }
4975
country(const char * hostname)4976 const char *country(const char *hostname)
4977 {
4978 #ifndef BITCHX_LITE
4979 static const struct {
4980 const char *code;
4981 const char *country;
4982 } domain[] = {
4983 {"AC", "Ascension Island" },
4984 {"AD", "Andorra" },
4985 {"AE", "United Arab Emirates" },
4986 {"AF", "Afghanistan" },
4987 {"AG", "Antigua and Barbuda" },
4988 {"AI", "Anguilla" },
4989 {"AL", "Albania" },
4990 {"AM", "Armenia" },
4991 {"AN", "Netherlands Antilles" },
4992 {"AO", "Angola" },
4993 {"AQ", "Antarctica (BURRR!)" },
4994 {"AR", "Argentina" },
4995 {"AS", "American Samoa" },
4996 {"AT", "Austria" },
4997 {"AU", "Australia" },
4998 {"AW", "Aruba" },
4999 {"AX", "Aland" },
5000 {"AZ", "Azerbaijan" },
5001 {"BA", "Bosnia and Herzegovina" },
5002 {"BB", "Barbados" },
5003 {"BD", "Bangladesh" },
5004 {"BE", "Belgium" },
5005 {"BF", "Burkina Faso" },
5006 {"BG", "Bulgaria" },
5007 {"BH", "Bahrain" },
5008 {"BI", "Burundi" },
5009 {"BJ", "Benin" },
5010 {"BM", "Bermuda" },
5011 {"BN", "Brunei Darussalam" },
5012 {"BO", "Bolivia" },
5013 {"BR", "Brazil" },
5014 {"BS", "Bahamas" },
5015 {"BT", "Bhutan" },
5016 {"BV", "Bouvet Island" },
5017 {"BW", "Botswana" },
5018 {"BY", "Belarus" },
5019 {"BZ", "Belize" },
5020 {"CA", "Canada (pHEAR)" },
5021 {"CC", "Cocos (Keeling) Islands" },
5022 {"CD", "Congo-Kinshasa" },
5023 {"CF", "Central African Republic" },
5024 {"CG", "Congo-Brazzaville" },
5025 {"CH", "Switzerland" },
5026 {"CI", "Cote D'Ivoire" },
5027 {"CK", "Cook Islands" },
5028 {"CL", "Chile" },
5029 {"CM", "Cameroon" },
5030 {"CN", "China" },
5031 {"CO", "Colombia" },
5032 {"CR", "Costa Rica" },
5033 {"CU", "Cuba" },
5034 {"CV", "Cape Verde" },
5035 {"CW", "Curacao" },
5036 {"CX", "Christmas Island" },
5037 {"CY", "Cyprus" },
5038 {"CZ", "Czech Republic" },
5039 {"DE", "Germany" },
5040 {"DJ", "Djibouti" },
5041 {"DK", "Denmark" },
5042 {"DM", "Dominica" },
5043 {"DO", "Dominican Republic" },
5044 {"DZ", "Algeria" },
5045 {"EC", "Ecuador" },
5046 {"EE", "Estonia" },
5047 {"EG", "Egypt" },
5048 {"EH", "Western Sahara" },
5049 {"ER", "Eritrea" },
5050 {"ES", "Spain" },
5051 {"ET", "Ethiopia" },
5052 {"EU", "European Union" },
5053 {"FI", "Finland" },
5054 {"FJ", "Fiji" },
5055 {"FK", "Falkland Islands" },
5056 {"FM", "Micronesia" },
5057 {"FO", "Faroe Islands" },
5058 {"FR", "France" },
5059 {"GA", "Gabon" },
5060 {"GB", "Great Britain" },
5061 {"GD", "Grenada" },
5062 {"GE", "Georgia" },
5063 {"GF", "French Guiana" },
5064 {"GG", "Guernsey" },
5065 {"GH", "Ghana" },
5066 {"GI", "Gibraltar" },
5067 {"GL", "Greenland" },
5068 {"GM", "Gambia" },
5069 {"GN", "Guinea" },
5070 {"GP", "Guadeloupe" },
5071 {"GQ", "Equatorial Guinea" },
5072 {"GR", "Greece" },
5073 {"GS", "S. Georgia and S. Sandwich Isles" },
5074 {"GT", "Guatemala" },
5075 {"GU", "Guam" },
5076 {"GW", "Guinea-Bissau" },
5077 {"GY", "Guyana" },
5078 {"HK", "Hong Kong" },
5079 {"HM", "Heard and McDonald Islands" },
5080 {"HN", "Honduras" },
5081 {"HR", "Croatia" },
5082 {"HT", "Haiti" },
5083 {"HU", "Hungary" },
5084 {"ID", "Indonesia" },
5085 {"IE", "Ireland" },
5086 {"IL", "Israel" },
5087 {"IM", "Isle of Man" },
5088 {"IN", "India" },
5089 {"IO", "British Indian Ocean Territory" },
5090 {"IQ", "Iraq" },
5091 {"IR", "Iran" },
5092 {"IS", "Iceland" },
5093 {"IT", "Italy" },
5094 {"JE", "Jersey" },
5095 {"JM", "Jamaica" },
5096 {"JO", "Jordan" },
5097 {"JP", "Japan" },
5098 {"KE", "Kenya" },
5099 {"KG", "Kyrgyzstan" },
5100 {"KH", "Cambodia" },
5101 {"KI", "Kiribati" },
5102 {"KM", "Comoros" },
5103 {"KN", "St. Kitts and Nevis" },
5104 {"KP", "North Korea" },
5105 {"KR", "South Korea" },
5106 {"KW", "Kuwait" },
5107 {"KY", "Cayman Islands" },
5108 {"KZ", "Kazakstan" },
5109 {"LA", "Laos" },
5110 {"LB", "Lebanon" },
5111 {"LC", "St. Lucia" },
5112 {"LI", "Liechtenstein" },
5113 {"LK", "Sri Lanka" },
5114 {"LR", "Liberia" },
5115 {"LS", "Lesotho" },
5116 {"LT", "Lithuania" },
5117 {"LU", "Luxembourg" },
5118 {"LV", "Latvia" },
5119 {"LY", "Libya" },
5120 {"MA", "Morocco" },
5121 {"MC", "Monaco" },
5122 {"MD", "Moldova" },
5123 {"ME", "Montenegro" },
5124 {"MG", "Madagascar" },
5125 {"MH", "Marshall Islands" },
5126 {"MK", "Macedonia" },
5127 {"ML", "Mali" },
5128 {"MM", "Myanmar" },
5129 {"MN", "Mongolia" },
5130 {"MO", "Macau" },
5131 {"MP", "Northern Mariana Islands" },
5132 {"MQ", "Martinique" },
5133 {"MR", "Mauritania" },
5134 {"MS", "Montserrat" },
5135 {"MT", "Malta" },
5136 {"MU", "Mauritius" },
5137 {"MV", "Maldives" },
5138 {"MW", "Malawi" },
5139 {"MX", "Mexico" },
5140 {"MY", "Malaysia" },
5141 {"MZ", "Mozambique" },
5142 {"NA", "Namibia" },
5143 {"NC", "New Caledonia" },
5144 {"NE", "Niger" },
5145 {"NF", "Norfolk Island" },
5146 {"NG", "Nigeria" },
5147 {"NI", "Nicaragua" },
5148 {"NL", "Netherlands" },
5149 {"NO", "Norway" },
5150 {"NP", "Nepal" },
5151 {"NR", "Nauru" },
5152 {"NU", "Niue" },
5153 {"NZ", "New Zealand" },
5154 {"OM", "Oman" },
5155 {"PA", "Panama" },
5156 {"PE", "Peru" },
5157 {"PF", "French Polynesia" },
5158 {"PG", "Papua New Guinea" },
5159 {"PH", "Philippines" },
5160 {"PK", "Pakistan" },
5161 {"PL", "Poland" },
5162 {"PM", "St. Pierre and Miquelon" },
5163 {"PN", "Pitcairn Island" },
5164 {"PR", "Puerto Rico" },
5165 {"PS", "Palestinian Territories" },
5166 {"PT", "Portugal" },
5167 {"PW", "Palau" },
5168 {"PY", "Paraguay" },
5169 {"QA", "Qatar" },
5170 {"RE", "Reunion Island" },
5171 {"RO", "Romania" },
5172 {"RS", "Serbia" },
5173 {"RU", "Russian Federation (pHEAR)" },
5174 {"RW", "Rwanda" },
5175 {"SA", "Saudi Arabia" },
5176 {"SB", "Solomon Islands" },
5177 {"SC", "Seychelles" },
5178 {"SD", "Sudan" },
5179 {"SE", "Sweden" },
5180 {"SG", "Singapore" },
5181 {"SH", "St. Helena" },
5182 {"SI", "Slovenia" },
5183 {"SJ", "Svalbard and Jan Mayen Islands" },
5184 {"SK", "Slovakia" },
5185 {"SL", "Sierra Leone" },
5186 {"SM", "San Marino" },
5187 {"SN", "Senegal" },
5188 {"SO", "Somalia" },
5189 {"SR", "Suriname" },
5190 {"ST", "Sao Tome and Principe" },
5191 {"SU", "Former USSR (pHEAR)" },
5192 {"SV", "El Salvador" },
5193 {"SX", "Sint Maarten" },
5194 {"SY", "Syria" },
5195 {"SZ", "Swaziland" },
5196 {"TC", "Turks and Caicos Islands" },
5197 {"TD", "Chad" },
5198 {"TF", "French Southern Territories" },
5199 {"TG", "Togo" },
5200 {"TH", "Thailand" },
5201 {"TJ", "Tajikistan" },
5202 {"TK", "Tokelau" },
5203 {"TL", "East Timor" },
5204 {"TM", "Turkmenistan" },
5205 {"TN", "Tunisia" },
5206 {"TO", "Tonga" },
5207 {"TP", "East Timor" },
5208 {"TR", "Turkey" },
5209 {"TT", "Trinidad and Tobago" },
5210 {"TV", "Tuvalu" },
5211 {"TW", "Taiwan" },
5212 {"TZ", "Tanzania" },
5213 {"UA", "Ukraine" },
5214 {"UG", "Uganda" },
5215 {"UK", "United Kingdom" },
5216 {"UM", "US Minor Outlying Islands" },
5217 {"US", "United States of America" },
5218 {"UY", "Uruguay" },
5219 {"UZ", "Uzbekistan" },
5220 {"VA", "Vatican City" },
5221 {"VC", "St. Vincent and the Grenadines" },
5222 {"VE", "Venezuela" },
5223 {"VG", "British Virgin Islands" },
5224 {"VI", "US Virgin Islands" },
5225 {"VN", "Vietnam" },
5226 {"VU", "Vanuatu" },
5227 {"WF", "Wallis and Futuna Islands" },
5228 {"WS", "Western Samoa" },
5229 {"YE", "Yemen" },
5230 {"YT", "Mayotte" },
5231 {"YU", "Yugoslavia" },
5232 {"ZA", "South Africa" },
5233 {"ZM", "Zambia" },
5234 {"ZR", "Zaire" },
5235 {"ZW", "Zimbabwe" },
5236 {"AERO", "Air Transport Industry" },
5237 {"ARPA", "Reverse DNS" },
5238 {"ASIA", "Asia-Pacific" },
5239 {"BIZ", "Business" },
5240 {"CAT", "Catalan Language" },
5241 {"COOP", "Cooperative Association" },
5242 {"COM", "Commercial" },
5243 {"EDU", "Educational Institution" },
5244 {"GOV", "United States Government" },
5245 {"INFO", "Informational" },
5246 {"INT", "International" },
5247 {"JOBS", "Employment Advertisements" },
5248 {"MIL", "United States Military" },
5249 {"MOBI", "Mobile Device" },
5250 {"MUSEUM", "Museum" },
5251 {"NET", "Network" },
5252 {"NAME", "Individuals" },
5253 {"ORG", "Organization" },
5254 {"PRO", "Professional" },
5255 {"TEL", "Contact Information" },
5256 {"TRAVEL", "Travel Industry" },
5257 {"XXX", "Porn" },
5258 {NULL, NULL}
5259 };
5260 const char *p;
5261 int i = 0;
5262
5263 if (!hostname || !*hostname || isdigit((unsigned char)hostname[strlen(hostname)-1]))
5264 return "unknown";
5265 if ((p = strrchr(hostname, '.')))
5266 p++;
5267 else
5268 p = hostname;
5269 for (i = 0; domain[i].code; i++)
5270 if (!my_stricmp(p, domain[i].code))
5271 return domain[i].country;
5272 #endif
5273 return "unknown";
5274 }
5275
5276