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