Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
BitchX
GitHub Repository: BitchX/BitchX1.3
Path: blob/master/source/irc.c
1069 views
1
/*
2
* ircII: a new irc client. I like it. I hope you will too!
3
*
4
* Written By Michael Sandrof
5
* Copyright(c) 1990
6
* See the COPYRIGHT file, or do a HELP IRCII COPYRIGHT
7
*/
8
9
#define __irc_c
10
11
#include "irc.h"
12
#include "struct.h"
13
14
static char cvsrevision[] = "$Id: irc.c 206 2012-06-13 12:34:32Z keaston $";
15
CVS_REVISION(irc_c)
16
17
#include <sys/types.h>
18
#include <sys/stat.h>
19
#include <pwd.h>
20
#ifdef USING_CURSES
21
#include <curses.h>
22
#endif
23
#include <stdarg.h>
24
25
#include "status.h"
26
#include "dcc.h"
27
#include "names.h"
28
#include "vars.h"
29
#include "input.h"
30
#include "alias.h"
31
#include "output.h"
32
#include "ircterm.h"
33
#include "exec.h"
34
#include "flood.h"
35
#include "screen.h"
36
#include "log.h"
37
#include "server.h"
38
#include "hook.h"
39
#include "keys.h"
40
#include "ircaux.h"
41
#include "commands.h"
42
#include "window.h"
43
#include "history.h"
44
#include "exec.h"
45
#include "notify.h"
46
#include "numbers.h"
47
#include "mail.h"
48
#include "debug.h"
49
#include "newio.h"
50
#include "timer.h"
51
#include "whowas.h"
52
#include "misc.h"
53
#include "gui.h"
54
#include "cdns.h"
55
#include "tcl_bx.h"
56
#include "ssl.h"
57
#include <pwd.h>
58
#define MAIN_SOURCE
59
#include "modval.h"
60
61
#ifdef __EMX__
62
#include <signame.h>
63
#endif
64
65
#ifndef VERSION
66
const char irc_version[] = "BitchX-1.3-git";
67
#else
68
const char irc_version[] = VERSION;
69
#endif
70
71
/* Format of bitchx_numver: MMmmpp
72
* MM = major version (eg 10 = 1.0)
73
* mm = minor version
74
* pp = patchlevel (00 = development, 01 = release)
75
*/
76
const unsigned long bitchx_numver = 120200;
77
78
/*
79
* INTERNAL_VERSION is the number that the special alias $V returns.
80
* Make sure you are prepared for floods, pestilence, hordes of locusts(
81
* and all sorts of HELL to break loose if you change this number.
82
* Its format is actually YYYYMMDD, for the _release_ date of the
83
* client..
84
*/
85
const char internal_version[] = "20210425";
86
87
int irc_port = IRC_PORT, /* port of ircd */
88
strip_ansi_in_echo,
89
current_on_hook = -1, /* used in the send_text()
90
* routine */
91
use_flow_control = USE_FLOW_CONTROL, /* true: ^Q/^S used for flow
92
* cntl */
93
current_numeric, /* this is negative of the
94
* current numeric! */
95
dumb_mode = 0, /* if true, IRCII is put in
96
* "dumb" mode */
97
bflag = 1,
98
99
use_input = 1, /* if 0, stdin is never
100
* checked */
101
waiting_out = 0, /* used by /WAIT command */
102
waiting_in = 0, /* used by /WAIT command */
103
who_mask = 0, /* keeps track of which /who
104
* switchs are set */
105
dead = 0,
106
inhibit_logging = 0,
107
#ifndef ONLY_STD_CHARS
108
startup_ansi = 1, /* display startup ansi */
109
#else
110
startup_ansi = 0, /* DO NOT display startup ansi */
111
#endif
112
auto_connect = 1, /* auto-connect to first server*/
113
114
background = 0,
115
do_check_pid = 0,
116
do_ignore_ajoin = 0,
117
#ifdef HAVE_SSL
118
do_use_ssl = 0,
119
#endif
120
run_level = 0,
121
122
foreground = 1,
123
reconnect = 0, /* reconnecting to old process */
124
use_nat_address = 0, /* use NAT address */
125
term_initialized = 0;
126
127
char zero[] = "0",
128
one[] = "1",
129
space[] = " ",
130
space_plus[] = " +",
131
space_minus[] = " -",
132
dot[] = ".",
133
star[] = "*",
134
comma[] = ",",
135
empty_string[] = "",
136
on[] = "ON",
137
off[] = "OFF";
138
139
const char *unknown_userhost = "<UNKNOWN>@<UNKNOWN>";
140
141
char oper_command = 0; /* true just after an oper() command is
142
* given. Used to tell the difference
143
* between an incorrect password generated by
144
* an oper() command and one generated when
145
* connecting to a new server */
146
struct sockaddr_foobar MyHostAddr; /* The local machine address */
147
struct sockaddr_foobar LocalHostAddr;
148
char *LocalHostName = NULL;
149
150
char *channel = NULL;
151
152
153
int inbound_line_mangler = 0,
154
logfile_line_mangler = 0,
155
operlog_line_mangler = 0,
156
outbound_line_mangler = 0;
157
158
159
160
char *invite_channel = NULL, /* last channel of an INVITE */
161
*ircrc_file = NULL, /* full path .ircrc file */
162
*bircrc_file = NULL, /* full path .ircrc file */
163
*my_path = NULL, /* path to users home dir */
164
*irc_path = NULL, /* paths used by /load */
165
*irc_lib = NULL, /* path to the ircII library */
166
*ircservers_file = NULL, /* name of server file */
167
nickname[NICKNAME_LEN + 1], /* users nickname */
168
hostname[NAME_LEN + 1], /* name of current host */
169
userhost[(NAME_LEN + 1) * 2],
170
realname[REALNAME_LEN + 1], /* real name of user */
171
username[NAME_LEN + 1], /* usernameof user */
172
attach_ttyname[500], /* ttyname for this term */
173
socket_path[500], /* ttyname for this term */
174
*forwardnick = NULL, /* used for /forward */
175
*send_umode = NULL, /* sent umode */
176
*args_str = NULL, /* list of command line args */
177
*last_notify_nick = NULL, /* last detected nickname */
178
*auto_str = NULL, /* auto response str */
179
*new_script = NULL, /* rephacement for .bitchxrc and .ircrc */
180
*cut_buffer = NULL; /* global cut_buffer */
181
182
int quick_startup = 0; /* set if we ignore .ircrc */
183
int cpu_saver = 0;
184
185
int use_socks = 0; /* do we use socks info to connect */
186
char *old_tty = NULL, /* re-attach tty and password */
187
*old_pass = NULL;
188
189
extern char *FromUserHost;
190
191
192
int cx_line = 0;
193
char cx_file[BIG_BUFFER_SIZE/4]; /* debug file info */
194
char cx_function[BIG_BUFFER_SIZE/4];
195
extern int doing_privmsg, doing_notice;
196
197
198
199
200
time_t idle_time = 0,
201
now = 0,
202
start_time;
203
fd_set readables, writables;
204
struct in_addr nat_address;
205
206
207
static void quit_response (char *, char *);
208
static void versionreply (void);
209
static char *parse_args (char **, int, char **);
210
static void remove_pid(void);
211
void do_ansi_logo(int);
212
213
extern void set_process_bits(fd_set *rd);
214
215
static volatile int cntl_c_hit = 0;
216
217
char version[] = _VERSION_;
218
219
static char *switch_help[] = {
220
"Usage: BitchX [switches] [nickname] [server list] \n",
221
" The [nickname] can be at most 15 characters long\n",
222
" The [server list] is a whitespace separate list of server name\n",
223
" The [switches] may be any or all of the following\n",
224
#ifndef WINNT
225
" -H <hostname>\tuses the virtual hostname if possible\n",
226
#endif
227
" -N do not auto-connect to the first server\n",
228
" -A do not display the startup ansi\n",
229
" -c <channel>\tjoins <channel> on startup. don\'t forget to escape the # using \\\n",
230
#if defined(WINNT) || defined(__EMX__)
231
" -b\t\tload bx-rc or irc-rc after connecting to a server\n",
232
#else
233
" -b\t\tload .bitchxrc or .ircrc after connecting to a server\n",
234
#endif
235
" -p <port>\tdefault server connection port (usually 6667)\n",
236
#ifndef WINNT
237
" -f\t\tyour terminal uses flow controls (^S/^Q), so BitchX shouldn't\n",
238
" -F\t\tyour terminal doesn't use flow control (default)\n",
239
#endif
240
" -d\t\truns BitchX in \"dumb\" terminal mode\n",
241
#if defined(WINNT) || defined(__EMX__)
242
" -q\t\tdoes not load ~/irc-rc\n",
243
#else
244
" -q\t\tdoes not load ~/.ircrc\n",
245
#endif
246
" -r file\tload file as list of servers\n",
247
" -n nickname\tnickname to use\n",
248
" -a\t\tadds default servers and command line servers to server list\n",
249
" -x\t\truns BitchX in \"debug\" mode\n",
250
" -Z\t\tuse NAT address when doing dcc.\n",
251
" -P\t\ttoggle check pid.nickname for running program.\n",
252
" -v\t\ttells you about the client's version\n",
253
#ifdef HAVE_SSL
254
" -s\t\tservers specified are SSL.\n",
255
#endif
256
" -i\t\tignores the autojoin list entries.\n",
257
#if defined(WINNT) || defined(__EMX__)
258
" -l <file>\tloads <file> in place of your irc-rc\n\
259
-L <file>\tloads <file> in place of your irc-rc and expands $ expandos\n",
260
#else
261
" -l <file>\tloads <file> in place of your .ircrc\n\
262
-L <file>\tloads <file> in place of your .ircrc and expands $ expandos\n",
263
#endif
264
#if !defined(WINNT) && !defined(__EMX__)
265
" -B\t\tforce BitchX to fork and return you to shell. pid check on.\n",
266
#endif
267
NULL };
268
269
char *time_format = NULL; /* XXX Bogus XXX */
270
#ifdef __EMX__
271
char *strftime_24hour = "%H:%M";
272
#else
273
char *strftime_24hour = "%R";
274
#endif
275
char *strftime_12hour = "%I:%M%p";
276
char time_str[61];
277
278
char saved_termvar[BUFSIZ];
279
280
void detachcmd(char *, char *, char *, char *);
281
282
283
int
284
munge_term_env_var(void)
285
{
286
char *termvar = getenv("TERM");
287
int i;
288
289
/*
290
* Initialize saved_termvar
291
*/
292
293
for (i = 0; i < BUFSIZ; i++)
294
saved_termvar[i] = '\0';
295
296
/*
297
* TERM var not there? It'll get detected later. Exit silently.
298
*/
299
300
if (!termvar)
301
return 0;
302
303
if (!strcmp(termvar, "xterm-256color"))
304
{
305
snprintf(saved_termvar, BUFSIZ, "TERM=%s", termvar);
306
return 1;
307
}
308
else if (!strcmp(termvar, "xterm"))
309
{
310
snprintf(saved_termvar, BUFSIZ, "TERM=%s", termvar);
311
return 1;
312
}
313
314
/*
315
* Add more if's here, if needed.
316
*/
317
}
318
319
void
320
restore_term_env_var(void)
321
{
322
if (strlen(saved_termvar) > 0)
323
{
324
putenv(saved_termvar);
325
}
326
}
327
328
329
/* update_clock: figUres out the current time and returns it in a nice format */
330
char *BX_update_clock(int flag)
331
{
332
static int min = -1,
333
hour = -1;
334
static time_t last_minute = -1;
335
time_t idlet;
336
static struct tm time_val;
337
time_t hideous;
338
int new_minute = 0;
339
int new_hour = 0;
340
341
hideous = now;
342
343
#if !defined(NO_CHEATING)
344
if (hideous / 60 > last_minute)
345
{
346
last_minute = hideous / 60;
347
time_val = *localtime(&hideous);
348
}
349
#else
350
time_val = *localtime(&hideous);
351
#endif
352
353
354
if (flag == RESET_TIME || time_val.tm_min != min || time_val.tm_hour != hour)
355
{
356
int ofs = from_server;
357
from_server = primary_server;
358
359
if (time_format) /* XXXX Bogus XXXX */
360
strftime(time_str, 60, time_format, &time_val);
361
else if (get_int_var(CLOCK_24HOUR_VAR))
362
strftime(time_str, 60, strftime_24hour, &time_val);
363
else
364
strftime(time_str, 60, strftime_12hour, &time_val);
365
366
lower(time_str);
367
if ((time_val.tm_min != min) || (time_val.tm_hour != hour))
368
{
369
int is_away = 0;
370
if (time_val.tm_hour != hour)
371
new_hour = 1;
372
new_minute = 1;
373
hour = time_val.tm_hour;
374
min = time_val.tm_min;
375
do_hook(TIMER_LIST, "%02d:%02d", hour, min);
376
if (min == 0 || new_hour)
377
do_hook(TIMER_HOUR_LIST, "%02d:%02d", hour, min);
378
idlet = hideous - idle_time;
379
if (from_server != -1)
380
is_away = get_server_away(from_server) ? 1 : 0;
381
if (do_hook(IDLE_LIST, "%lu", (unsigned long)idlet / 60))
382
{
383
if (is_away && new_hour && get_int_var(TIMESTAMP_AWAYLOG_HOURLY_VAR))
384
logmsg(LOG_CRAP, NULL, 4, NULL);
385
check_auto_away(idlet);
386
}
387
check_channel_limits();
388
}
389
if (!((hideous - start_time) % 20))
390
check_serverlag();
391
from_server = ofs;
392
if (flag != RESET_TIME || new_minute)
393
return time_str;
394
else
395
return NULL;
396
}
397
if (flag == GET_TIME)
398
return time_str;
399
else
400
return NULL;
401
}
402
403
void reset_clock(Window *win, char *unused, int unused1)
404
{
405
update_clock(RESET_TIME);
406
update_all_status(win, NULL, 0);
407
}
408
409
410
411
/* sig_refresh_screen: the signal-callable version of refresh_screen */
412
SIGNAL_HANDLER(sig_refresh_screen)
413
{
414
refresh_screen(0, NULL);
415
}
416
417
/* irc_exit: cleans up and leaves */
418
SIGNAL_HANDLER(irc_exit_old)
419
{
420
irc_exit(1,NULL, NULL);
421
}
422
423
volatile int dead_children_processes;
424
425
/* This is needed so that the fork()s we do to read compressed files dont
426
* sit out there as zombies and chew up our fd's while we read more.
427
*/
428
SIGNAL_HANDLER(child_reap)
429
{
430
dead_children_processes++;
431
#ifdef __EMX__
432
my_signal(SIGCHLD, SIG_IGN, 0);
433
#endif
434
}
435
436
SIGNAL_HANDLER(nothing)
437
{
438
/* nothing to do! */
439
}
440
441
SIGNAL_HANDLER(sigpipe)
442
{
443
static int sigpipe_hit = 0;
444
sigpipe_hit++;
445
446
}
447
448
#if 0
449
SIGNAL_HANDLER(sigusr2)
450
{
451
mtrace();
452
}
453
SIGNAL_HANDLER(sigusr3)
454
{
455
muntrace();
456
}
457
#endif
458
459
/* irc_exit: cleans up and leaves */
460
void BX_irc_exit (int really_quit, char *reason, char *format, ...)
461
{
462
char buffer[BIG_BUFFER_SIZE];
463
464
logger(current_window, NULL, 0);
465
if (get_int_var(MSGLOG_VAR))
466
log_toggle(0, NULL);
467
if (format)
468
{
469
va_list arglist;
470
va_start(arglist, format);
471
vsprintf(buffer, format, arglist);
472
va_end(arglist);
473
}
474
else
475
sprintf(buffer, "%s -- just do it.",irc_version);
476
477
if (really_quit)
478
{
479
put_it("%s", convert_output_format("$G Signon time : $0-", "%s", my_ctime(start_time)));
480
put_it("%s", convert_output_format("$G Signoff time : $0-", "%s", my_ctime(now)));
481
put_it("%s", convert_output_format("$G Total uptime : $0-", "%s", convert_time(now - start_time)));
482
}
483
do_hook(EXIT_LIST, "%s", reason ? reason : buffer);
484
485
close_all_servers(reason ? reason : buffer);
486
487
put_it("%s", buffer ? buffer : reason ? reason : empty_string);
488
489
490
clean_up_processes();
491
if (!dumb_mode && term_initialized)
492
{
493
cursor_to_input(); /* Needed so that ircII doesn't gobble
494
* the last line of the kill. */
495
term_cr();
496
term_clear_to_eol();
497
term_reset();
498
}
499
500
destroy_call_stack();
501
502
#if defined(THREAD) && defined(WANT_NSLOOKUP)
503
kill_dns();
504
#endif
505
506
remove_pid();
507
if (really_quit)
508
{
509
510
#ifdef GUI
511
gui_exit();
512
#else
513
#if defined(WANT_DETACH) && !defined(GUI)
514
kill_attached_if_needed(0);
515
#endif
516
fprintf(stdout, "\r");
517
fflush(stdout);
518
exit(0);
519
#endif
520
}
521
}
522
523
#ifndef WANT_CORE
524
volatile int segv_recurse = 0;
525
/* sigsegv: something to handle segfaults in a nice way */
526
/* this needs to be changed to *NOT* use printf(). */
527
SIGNAL_HANDLER(coredump)
528
{
529
#if defined(WINNT)
530
extern char *sys_siglist[];
531
#endif
532
if (segv_recurse)
533
_exit(1);
534
segv_recurse = 1;
535
panic_dump_call_stack();
536
537
#ifdef TDEBUG
538
putlog(LOG_ALL, "*", "Error logged. %s at (%d) %s", cx_file, cx_line, cx_function?cx_function:empty_string);
539
#endif
540
printf("\n\r\n\rIRCII has been terminated by a [%s]\n\r", sys_siglist[unused]);
541
printf("Please email " BUG_EMAIL "\n\r");
542
printf("with as much detail as possible about what you were doing when it happened.\n\r");
543
printf("Please include the version of IRCII (%s) and type of system in the report.\n\r", irc_version);
544
fflush(stdout);
545
irc_exit(1, "Hmmmm... BitchX error!!!! unusual :)", NULL);
546
}
547
#endif
548
549
/*
550
* quit_response: Used by irc_io when called from irc_quit to see if we got
551
* the right response to our question. If the response was affirmative, the
552
* user gets booted from irc. Otherwise, life goes on.
553
*/
554
static void quit_response(char *dummy, char *ptr)
555
{
556
int len;
557
558
if ((len = strlen(ptr)) != 0)
559
if (!my_strnicmp(ptr, "yes", len))
560
irc_exit(1, NULL, "IRC][ %s: Rest in peace", irc_version);
561
}
562
563
/* irc_quit: prompts the user if they wish to exit, then does the right thing */
564
void irc_quit(char key, char * ptr)
565
{
566
static int in_it = 0;
567
568
if (in_it)
569
return;
570
in_it = 1;
571
add_wait_prompt("Do you really want to quit? ", quit_response, empty_string, WAIT_PROMPT_LINE, 1);
572
in_it = 0;
573
}
574
575
/*
576
* cntl_c: emergency exit.... if somehow everything else freezes up, hitting
577
* ^C five times should kill the program.
578
*/
579
SIGNAL_HANDLER(cntl_c)
580
{
581
582
if (cntl_c_hit++ >= 4)
583
irc_exit(1, "User abort with 5 Ctrl-C's", NULL);
584
else if (cntl_c_hit > 1)
585
kill(getpid(), SIGALRM);
586
}
587
588
SIGNAL_HANDLER(sig_user1)
589
{
590
bitchsay("Got SIGUSR1, closing DCC connections and EXECed processes");
591
close_all_dcc();
592
clean_up_processes();
593
}
594
595
596
SIGNAL_HANDLER(sig_detach)
597
{
598
detachcmd(NULL, NULL, NULL, NULL);
599
}
600
601
void set_detach_on_hup(Window *dummy, char *unused, int value)
602
{
603
if(value)
604
my_signal(SIGHUP, sig_detach, 0);
605
else
606
my_signal(SIGHUP, irc_exit_old, 0);
607
}
608
609
/* shows the version of irc */
610
static void versionreply(void)
611
{
612
printf("BitchX version %s (%s)\n\r", irc_version, internal_version);
613
exit (0);
614
}
615
616
#ifndef RAND_MAX
617
#define RAND_MAX 2147483647
618
#endif
619
620
void display_bitchx(int j)
621
{
622
623
int i = 0;
624
int old_strip_ansi = strip_ansi_in_echo;
625
626
strip_ansi_in_echo = 0;
627
628
if (j == -1)
629
#ifdef ASCII_LOGO
630
i = (int) (5.0*rand()/RAND_MAX);
631
#else
632
i = (int) (17.0*rand()/RAND_MAX);
633
#endif
634
else
635
i = j;
636
637
if (!startup_ansi)
638
return;
639
640
#if !defined(WINNT) && !defined(__EMX__)
641
charset_ibmpc();
642
#endif
643
644
do_ansi_logo(i);
645
#if !defined(WINNT) && !defined(__EMX__)
646
#if defined(LATIN1)
647
charset_lat1();
648
#elif defined(CHARSET_CUSTOM)
649
charset_cst();
650
#endif
651
652
#endif
653
strip_ansi_in_echo = old_strip_ansi;
654
}
655
656
657
658
/*
659
* parse_args: parse command line arguments for irc, and sets all initial
660
* flags, etc.
661
*
662
* major rewrite 12/22/94 -jfn
663
*
664
*
665
* Im going to break backwards compatability here: I think that im
666
* safer in doing this becuase there are a lot less shell script with
667
* the command line flags then there are ircII scripts with old commands/
668
* syntax that would be a nasty thing to break..
669
*
670
* Sanity check:
671
* Supported flags: -b, -l, -v, -c, -p, -f, -F, -L, -a, -S, -z
672
* New (changed) flags: -s, -I, -i, -n
673
*
674
* Rules:
675
* Each flag must be included by a hyphen: -lb <filename> is not the
676
* same as -l <filename> -b any more...
677
* Each flag may or may not have a space between the flag and the argument.
678
* -lfoo is the same as -l foo
679
* Anything surrounded by quotation marks is honored as one word.
680
* The -c, -p, -L, -l, -s, -z flags all take arguments. If no argumenTs
681
* are given between the flag and the next flag, an error
682
* message is printed and the program is halted.
683
* Exception: the -s flag will be accepted without a argument.
684
* (ick: backwards compatability sucks. ;-)
685
* Arguments occuring after a flag that does not take an argument
686
* will be parsed in the following way: the first instance
687
* will be an assumed nickname, and the second instance will
688
* will be an assumed server. (some semblance of back compat.)
689
* The -bl sequence will emit a depreciated feature warning.
690
* The -I flag forces you to become invisible <NOT YET SUPPORTED>
691
* The -i flag forces you to become visible <NOT YET SUPPORTED>
692
* The -X flag forces ircII to become an X application <NOT YET SUPPORTED>
693
* The -n flag means "nickname"
694
*
695
* Bugs:
696
* The -s flag is hard to use without an argument unless youre careful.
697
*/
698
#ifdef CLOAKED
699
extern char proctitlestr[140];
700
extern char **Argv;
701
extern char *LastArgv;
702
#endif
703
704
705
static char *parse_args (char *argv[], int argc, char **envp)
706
{
707
int ac;
708
int add_servers = 0;
709
#if !defined(WINNT)
710
struct passwd *entry;
711
#endif
712
char *channel = NULL;
713
struct hostent * hp;
714
char *ptr;
715
716
*nickname = 0;
717
718
#ifdef CLOAKED
719
Argv = argv;
720
while (*envp)
721
envp++;
722
LastArgv = envp[-1] + strlen(envp[-1]);
723
#endif
724
725
for ( ac = 1; ac < argc; ac++ )
726
{
727
if (argv[ac][0] == '-')
728
{
729
switch (argv[ac][1]) {
730
731
case 'A': /* turn off startup ansi */
732
startup_ansi = 0;
733
break;
734
case 'v': /* Output ircII version */
735
{
736
versionreply();
737
/* NOTREACHED */
738
}
739
740
case 'c': /* Default channel to join */
741
{
742
char *what = empty_string;
743
744
if (argv[ac][2])
745
what = &(argv[ac][2]);
746
else if (argv[ac+1] && argv[ac+1][0] != '-')
747
{
748
what = argv[ac+1];
749
ac++;
750
}
751
else
752
{
753
fprintf(stderr, "Missing parameter after -c\n");
754
exit(1);
755
}
756
malloc_strcpy(&channel, what);
757
break;
758
}
759
760
case 'p': /* Default port to use */
761
{
762
char *what = empty_string;
763
if (reconnect)
764
{
765
what = getpass("Enter password : ");
766
if (what && *what)
767
malloc_strcpy(&old_pass, what);
768
break;
769
}
770
771
if (argv[ac][2])
772
what = &argv[ac][2];
773
else if (argv[ac+1] && argv[ac+1][0] != '-')
774
{
775
what = argv[ac+1];
776
ac++;
777
}
778
else
779
{
780
fprintf(stderr, "Missing parameter after -p\n");
781
exit(1);
782
}
783
irc_port = my_atol(what);
784
break;
785
}
786
#ifndef WINNT
787
case 'f': /* Use flow control */
788
{
789
use_flow_control = 1;
790
if (argv[ac][2])
791
fprintf(stderr, "Ignoring junk after -f\n");
792
break;
793
}
794
795
case 'F': /* dont use flow control */
796
{
797
use_flow_control = 0;
798
if (argv[ac][2])
799
fprintf(stderr, "Ignoring junk after -F\n");
800
break;
801
}
802
#endif
803
case 'd': /* use dumb mode */
804
{
805
dumb_mode = 1;
806
if (argv[ac][2])
807
fprintf(stderr, "Ignoring junk after -d\n");
808
break;
809
}
810
811
case 'l': /* Load some file instead of ~/.ircrc */
812
{
813
char *what = empty_string;
814
815
if (argv[ac][2])
816
what = &argv[ac][2];
817
else if (argv[ac+1] && argv[ac+1][0] != '-')
818
{
819
what = argv[ac+1];
820
ac++;
821
}
822
else
823
{
824
fprintf(stderr, "Missing argument to -l\n");
825
exit(1);
826
}
827
malloc_strcpy(&new_script, what);
828
break;
829
}
830
831
case 'L': /* load and expand */
832
{
833
char *what = empty_string;
834
835
if (argv[ac][2])
836
what = &argv[ac][2];
837
else if (argv[ac+1] && argv[ac+1][0] != '-')
838
{
839
what = argv[ac+1];
840
ac++;
841
}
842
else
843
{
844
fprintf(stderr, "Missing argument to -L\n");
845
exit(1);
846
}
847
malloc_strcpy(&ircrc_file, what);
848
/* malloc_strcat(&ircrc_file, " -");*/
849
break;
850
}
851
852
case 'r': /* Load list of servers from this file */
853
{
854
char *what = empty_string;
855
856
if (argv[ac][2])
857
what = &argv[ac][2];
858
else if (argv[ac+1] && argv[ac+1][0] != '-')
859
{
860
what = argv[ac+1];
861
ac++;
862
}
863
else
864
fprintf(stderr, "Missing argumenT to -r\n");
865
866
if (*what)
867
{
868
add_servers = 1;
869
malloc_strcpy(&ircservers_file, what);
870
}
871
break;
872
}
873
case 'R':
874
fprintf(stderr, "Use \"scr-bx\" to reconnect\r\n");
875
exit(1);
876
break;
877
case 'a': /* add server, not replace */
878
{
879
add_servers = 1;
880
if (argv[ac][2])
881
fprintf(stderr, "Ignoring junk after -a\n");
882
break;
883
}
884
885
case 'q': /* quick startup -- no .ircrc */
886
{
887
quick_startup = 1;
888
if (argv[ac][2])
889
fprintf(stderr, "Ignoring junk after -q\n");
890
break;
891
}
892
893
case 'b':
894
{
895
bflag = 0;
896
break;
897
}
898
899
case 'B':
900
{
901
if (argv[ac][2] && argv[ac][2] != 'l')
902
fprintf(stderr, "Ignoring junk after -B\n");
903
else if (argv[ac][2] == 'l')
904
{
905
fprintf(stderr, "Usage of -bl is decprecated: use -b -l instead.\n");
906
exit(1);
907
}
908
/* dumb_mode = 1;*/
909
/* use_input = 0;*/
910
background = 1;
911
}
912
case 'P':
913
{
914
do_check_pid ^= 1;
915
break;
916
}
917
case 'n':
918
{
919
char *what = empty_string;
920
921
if (argv[ac][2])
922
what = &(argv[ac][2]);
923
else if (argv[ac+1] && argv[ac+1][0] != '-')
924
{
925
what = argv[ac+1];
926
ac++;
927
}
928
else
929
{
930
fprintf(stderr,"Missing argument for -n\n");
931
exit(1);
932
}
933
strmcpy(nickname, what, NICKNAME_LEN);
934
break;
935
}
936
case 'N':
937
{
938
auto_connect = 0;
939
break;
940
}
941
case 'x': /* set server debug */
942
{
943
x_debug = (unsigned long)0xffffffff;
944
if (argv[ac][2])
945
fprintf(stderr, "Ignoring junk after -x\n");
946
break;
947
}
948
case 'Z':
949
{
950
use_nat_address = 1;
951
break;
952
}
953
954
case 'z':
955
{
956
char *what;
957
if (argv[ac][2])
958
what = &argv[ac][2];
959
else if (argv[ac+1] && argv[ac+1][0] != '-')
960
{
961
what = argv[ac+1];
962
ac++;
963
}
964
else
965
break;
966
strmcpy(username, what, NAME_LEN);
967
break;
968
}
969
case 'H':
970
{
971
char *what = empty_string;
972
973
if (argv[ac][2])
974
what = &(argv[ac][2]);
975
else if (argv[ac+1] && argv[ac+1][0] != '-')
976
{
977
what = argv[ac+1];
978
ac++;
979
}
980
else
981
{
982
fprintf(stderr, "You forgot to specify a hostname\n");
983
984
exit(1);
985
}
986
malloc_strcpy(&LocalHostName, what);
987
break;
988
}
989
case 'S':
990
use_socks = 1;
991
break;
992
case 'i':
993
do_ignore_ajoin = 1;
994
break;
995
#ifdef HAVE_SSL
996
case 's':
997
do_use_ssl = 1;
998
break;
999
#endif
1000
case '\0':
1001
break; /* ignore - alone */
1002
1003
default:
1004
fprintf(stderr, "Unknown flag: %s\n",argv[ac]);
1005
case 'h':
1006
{
1007
int t = 0;
1008
1009
while(switch_help[t])
1010
{
1011
fprintf(stderr, "%s", switch_help[t]);
1012
t++;
1013
}
1014
exit(1);
1015
}
1016
} /* End of switch */
1017
}
1018
else
1019
{
1020
if (!strchr(argv[ac], '.') && !strchr(argv[ac], ',') && !*nickname)
1021
strmcpy(nickname, argv[ac], NICKNAME_LEN);
1022
else
1023
build_server_list(argv[ac]);
1024
#ifdef HAVE_SSL
1025
do_use_ssl = 0;
1026
#endif
1027
}
1028
}
1029
1030
if (!*nickname && (ptr = getenv("IRCNICK")))
1031
strmcpy(nickname, ptr, NICKNAME_LEN);
1032
1033
if (!ircservers_file)
1034
#if defined(WINNT) || defined(__EMX__)
1035
malloc_strcpy(&ircservers_file, "irc-serv");
1036
#else
1037
malloc_strcpy(&ircservers_file, ".ircservers");
1038
#endif
1039
/* v-- right there was a '!' that should not have been there. */
1040
if ((ptr = getenv("IRCLIB")))
1041
{
1042
malloc_strcpy(&irc_lib, ptr);
1043
malloc_strcat(&irc_lib, "/");
1044
}
1045
else
1046
malloc_strcpy(&irc_lib, IRCLIB);
1047
1048
if (!ircrc_file && (ptr = getenv("IRCRC")))
1049
malloc_strcpy(&ircrc_file, ptr);
1050
1051
if ((ptr = getenv("IRCUMODE")))
1052
malloc_strcpy(&send_umode, ptr);
1053
1054
if ((ptr = getenv("IRCNAME")))
1055
strmcpy(realname, ptr, REALNAME_LEN);
1056
else if ((ptr = getenv("NAME")))
1057
strmcpy(realname, ptr, REALNAME_LEN);
1058
1059
if ((ptr = getenv("IRCPATH")))
1060
malloc_strcpy(&irc_path, ptr);
1061
else
1062
{
1063
#ifdef IRCPATH
1064
malloc_strcpy(&irc_path, IRCPATH);
1065
#else
1066
malloc_strcpy(&irc_path, ".:~/.irc:");
1067
malloc_strcat(&irc_path, irc_lib);
1068
malloc_strcat(&irc_path, "script");
1069
#endif
1070
}
1071
1072
set_string_var(LOAD_PATH_VAR, irc_path);
1073
new_free(&irc_path);
1074
1075
/*
1076
* Yes... this is EXACTLY what you think it is. And if you don't know..
1077
* then I'm not about to tell you! -- Jake [WinterHawk] Khuon
1078
*
1079
* Here we determine our username. It may be set above, by the -z command line
1080
* option. If not check IRCUSER, then USER, then the IDENT_HACK file, then
1081
* fallback to gecos below.
1082
*/
1083
if (!*username && (ptr = getenv("IRCUSER"))) strmcpy(username, ptr, NAME_LEN);
1084
else if (!*username && (ptr = getenv("USER"))) strmcpy(username, ptr, NAME_LEN);
1085
else if (!*username)
1086
{
1087
#ifdef IDENT_FAKE
1088
char *p = NULL, *q = NULL;
1089
FILE *f;
1090
malloc_sprintf(&p, "~/%s", get_string_var(IDENT_HACK_VAR));
1091
q = expand_twiddle(p);
1092
if ((f = fopen(q, "r")))
1093
{
1094
fgets(username, NAME_LEN, f);
1095
if (*username && strchr(username, '\n'))
1096
username[strlen(username)-1] = 0;
1097
}
1098
fclose(f);
1099
new_free(&p); new_free(&q);
1100
if (!*username)
1101
#endif
1102
strmcpy(username, "Unknown", NAME_LEN);
1103
1104
}
1105
1106
#ifndef WINNT
1107
if ((entry = getpwuid(getuid())))
1108
{
1109
if (!*realname && entry->pw_gecos && *(entry->pw_gecos))
1110
{
1111
#ifdef GECOS_DELIMITER
1112
if ((ptr = index(entry->pw_gecos, GECOS_DELIMITER)))
1113
*ptr = (char) 0;
1114
#endif
1115
if ((ptr = strchr(entry->pw_gecos, '&')) == NULL)
1116
strmcpy(realname, entry->pw_gecos, REALNAME_LEN);
1117
else {
1118
int len = ptr - entry->pw_gecos;
1119
1120
if (len < REALNAME_LEN && *(entry->pw_name)) {
1121
char *q = realname + len;
1122
1123
strmcpy(realname, entry->pw_gecos, len);
1124
strmcat(realname, entry->pw_name, REALNAME_LEN);
1125
strmcat(realname, ptr + 1, REALNAME_LEN);
1126
if (islower((unsigned char)*q) && (q == realname || isspace((unsigned char)*(q - 1))))
1127
*q = toupper(*q);
1128
} else
1129
strmcpy(realname, entry->pw_gecos, REALNAME_LEN);
1130
}
1131
}
1132
if (entry->pw_name && *(entry->pw_name) && !*username)
1133
strmcpy(username, entry->pw_name, NAME_LEN);
1134
if (entry->pw_dir && *(entry->pw_dir))
1135
malloc_strcpy(&my_path, entry->pw_dir);
1136
}
1137
#else
1138
{
1139
u_long size=NAME_LEN+1;
1140
if (!(ptr = getenv("IRCUSER")))
1141
strcpy(username, "unknown");
1142
else
1143
strncpy(username,ptr, size);
1144
}
1145
#endif
1146
1147
if ((ptr = getenv("HOME")))
1148
malloc_strcpy(&my_path, ptr);
1149
else if (!my_path || !*my_path)
1150
#ifdef WINNT
1151
malloc_strcpy(&my_path, empty_string);
1152
#else
1153
malloc_strcpy(&my_path, "/");
1154
#endif
1155
#if defined(WINNT) || defined(__EMX__)
1156
convert_unix(my_path);
1157
#endif
1158
if (!*realname)
1159
strmcpy(realname, "* I'm too lame to read BitchX.doc *", REALNAME_LEN);
1160
1161
if (!LocalHostName && ((ptr = getenv("IRC_HOST")) || (ptr = getenv("IRCHOST"))))
1162
LocalHostName = m_strdup(ptr);
1163
1164
if ((gethostname(hostname, sizeof(hostname))))
1165
if (!LocalHostName)
1166
exit(1);
1167
1168
if (LocalHostName)
1169
{
1170
printf("Your hostname appears to be [%s]\n", LocalHostName);
1171
#ifndef IPV6
1172
memset((void *)&LocalHostAddr, 0, sizeof(LocalHostAddr));
1173
if ((hp = gethostbyname(LocalHostName)))
1174
memcpy((void *)&LocalHostAddr.sf_addr, hp->h_addr, sizeof(struct in_addr));
1175
}
1176
else
1177
{
1178
if ((hp = gethostbyname(hostname)))
1179
memcpy((char *) &MyHostAddr.sf_addr, hp->h_addr, sizeof(struct in_addr));
1180
#endif
1181
}
1182
1183
if (!nickname || !*nickname)
1184
strmcpy(nickname, username, NICKNAME_LEN);
1185
1186
if (!check_nickname(nickname))
1187
{
1188
fprintf(stderr, "Illegal nickname %s\n", nickname);
1189
fprintf(stderr, "Please restart IRC II with a valid nickname\n");
1190
exit(1);
1191
}
1192
if (ircrc_file == NULL)
1193
{
1194
ircrc_file = (char *) new_malloc(strlen(my_path) + strlen(IRCRC_NAME) + 1);
1195
strcpy(ircrc_file, my_path);
1196
strcat(ircrc_file, IRCRC_NAME);
1197
}
1198
if (bircrc_file == NULL)
1199
#if defined(WINNT) || defined(__EMX__)
1200
malloc_sprintf(&bircrc_file, "%s/bx-rc", my_path);
1201
#else
1202
malloc_sprintf(&bircrc_file, "%s/.bitchxrc", my_path);
1203
#endif
1204
1205
if ((ptr = getenv("IRCPORT")))
1206
irc_port = my_atol(ptr);
1207
1208
if ((ptr = getenv("IRCSERVER")))
1209
build_server_list(ptr);
1210
1211
if (!server_list_size() || add_servers)
1212
{
1213
if (!read_server_file(ircservers_file) && !server_list_size())
1214
{
1215
#ifdef DEFAULT_SERVER
1216
char *ptr = NULL;
1217
malloc_strcpy(&ptr, DEFAULT_SERVER);
1218
build_server_list(ptr);
1219
new_free(&ptr);
1220
1221
#endif
1222
from_server = -1;
1223
}
1224
}
1225
return (channel);
1226
}
1227
1228
1229
1230
/*
1231
* io() is a ONE TIME THROUGH loop! It simply does ONE check on the
1232
* file descriptors, and if there is nothing waiting, it will time
1233
* out and drop out. It does everything as far as checking for exec,
1234
* dcc, ttys, notify, the whole ball o wax, but it does NOT iterate!
1235
*
1236
* You should usually NOT call io() unless you are specifically waiting
1237
* for something from a file descriptor. It doesnt look like bad things
1238
* will happen if you call this elsewhere, but its long time behavior has
1239
* not been observed. It *does* however, appear to be much more reliable
1240
* then the old irc_io, and i even know how this works. >;-)
1241
*/
1242
extern void set_screens (fd_set *, fd_set *);
1243
1244
void BX_io (const char *what)
1245
{
1246
static int first_time = 1,
1247
level = 0;
1248
long clock_timeout = 0,
1249
timer_timeout = 0,
1250
server_timeout = 0,
1251
real_timeout = 0;
1252
static struct timeval my_now,
1253
my_timer,
1254
*time_ptr = &my_timer;
1255
1256
int hold_over,
1257
rc;
1258
fd_set rd,
1259
wd;
1260
static int old_level = 0;
1261
static const char *caller[51] = { NULL }; /* XXXX */
1262
static int last_warn = 0;
1263
1264
level++;
1265
1266
get_time(&my_now);
1267
now = my_now.tv_sec;
1268
1269
if (x_debug & DEBUG_WAITS)
1270
{
1271
if (level != old_level)
1272
{
1273
yell("Moving from io level [%d] to level [%d] from [%s]", old_level, level, what);
1274
old_level = level;
1275
}
1276
}
1277
1278
1279
if (level && (level - last_warn == 5))
1280
{
1281
last_warn = level;
1282
yell("io's nesting level is [%d], [%s]<-[%s]<-[%s]<-[%s]<-[%s]<-[%s]", level, what, caller[level-1], caller[level-2], caller[level-3], caller[level-4], caller[level-5]);
1283
if ((level % 30) == 0)
1284
ircpanic("Ahoy there matey! Abandon ship!");
1285
return;
1286
}
1287
else if (level && (last_warn -level == 5))
1288
last_warn -= 5;
1289
1290
caller[level] = what;
1291
1292
/* CHECK FOR CPU SAVER MODE */
1293
if (!cpu_saver && get_int_var(CPU_SAVER_AFTER_VAR))
1294
if (now - idle_time > get_int_var(CPU_SAVER_AFTER_VAR) * 60)
1295
cpu_saver_on(0, NULL);
1296
1297
rd = readables;
1298
wd = writables;
1299
FD_ZERO(&wd);
1300
FD_ZERO(&rd);
1301
1302
#ifndef GUI
1303
set_screens(&rd, &wd);
1304
#endif
1305
server_timeout = set_server_bits(&rd, &wd);
1306
set_process_bits(&rd);
1307
set_socket_read(&rd, &wd);
1308
set_nslookupfd(&rd);
1309
#ifdef GUI
1310
gui_setfd(&rd);
1311
#endif
1312
1313
clock_timeout = (60 - (my_now.tv_sec % 60)) * 1000;
1314
if (cpu_saver && get_int_var(CPU_SAVER_EVERY_VAR))
1315
clock_timeout += (get_int_var(CPU_SAVER_EVERY_VAR) - 1) * 60000;
1316
1317
timer_timeout = TimerTimeout();
1318
1319
if ((hold_over = unhold_windows()))
1320
real_timeout = 0;
1321
else if (timer_timeout <= clock_timeout)
1322
real_timeout = timer_timeout;
1323
else
1324
real_timeout = clock_timeout;
1325
1326
if(server_timeout && (server_timeout == -1 || server_timeout < real_timeout))
1327
real_timeout = server_timeout;
1328
1329
time_ptr = &my_timer;
1330
1331
if (real_timeout == -1)
1332
time_ptr = NULL;
1333
else
1334
{
1335
time_ptr->tv_sec = real_timeout / 1000;
1336
time_ptr->tv_usec = ((real_timeout % 1000) * 1000);
1337
}
1338
1339
/* GO AHEAD AND WAIT FOR SOME DATA TO COME IN */
1340
switch ((rc = new_select(&rd, &wd, time_ptr)))
1341
{
1342
case 0:
1343
if(server_timeout)
1344
do_idle_server();
1345
break;
1346
case -1:
1347
{
1348
/* if we just got a sigint */
1349
first_time = 0;
1350
if (cntl_c_hit)
1351
{
1352
edit_char('\003');
1353
/* cntl_c_hit = 0; */
1354
}
1355
else if (errno != EINTR)
1356
yell("Select failed with [%s]", strerror(errno));
1357
break;
1358
1359
}
1360
1361
/* we got something on one of the descriptors */
1362
default:
1363
{
1364
cntl_c_hit = 0;
1365
now = time(NULL);
1366
make_window_current(NULL);
1367
do_server(&rd, &wd);
1368
do_processes(&rd);
1369
do_screens(&rd);
1370
#ifdef WANT_CDCC
1371
dcc_sendfrom_queue();
1372
#endif
1373
dcc_check_idle();
1374
print_nslookup(&rd);
1375
scan_sockets(&rd, &wd);
1376
#ifdef GUI
1377
scan_gui(&rd);
1378
#endif
1379
break;
1380
}
1381
}
1382
1383
now = time(NULL);
1384
ExecuteTimers();
1385
#ifdef WANT_TCL
1386
check_utimers();
1387
#endif
1388
send_from_server_queue();
1389
get_child_exit(-1);
1390
1391
if (!hold_over)
1392
cursor_to_input();
1393
1394
1395
#ifdef WANT_LLOOK
1396
if (get_int_var(LLOOK_VAR) && from_server > -1 && !get_server_linklook(from_server))
1397
{
1398
if (now - get_server_linklook_time(from_server) > get_int_var(LLOOK_DELAY_VAR))
1399
{
1400
set_server_linklook(from_server, get_server_linklook(from_server)+1);
1401
my_send_to_server(from_server, "LINKS");
1402
set_server_linklook_time(from_server, now);
1403
}
1404
}
1405
#endif
1406
if (update_clock(RESET_TIME))
1407
{
1408
do_notify();
1409
#ifdef WANT_TCL
1410
check_timers();
1411
#endif
1412
clean_whowas_chan_list();
1413
clean_whowas_list();
1414
clean_flood_list();
1415
clean_split_server_list(CHAN_SPLIT, 1800);
1416
#ifdef WANT_LLOOK
1417
clean_split_server_list(LLOOK_SPLIT, 3600);
1418
#endif
1419
if (get_int_var(CLOCK_VAR) || check_mail_status())
1420
{
1421
update_all_status(current_window, NULL, 0);
1422
cursor_to_input();
1423
}
1424
check_server_connect(from_server);
1425
}
1426
1427
/* (set in term.c) -- we should redraw the screen here */
1428
if (need_redraw)
1429
refresh_screen(0, NULL);
1430
1431
FromUserHost = empty_string;
1432
1433
1434
alloca(0);
1435
caller[level] = NULL;
1436
level--;
1437
return;
1438
}
1439
1440
char pidfile[80];
1441
1442
void check_pid(void)
1443
{
1444
char *p = NULL;
1445
FILE *t;
1446
if (!do_check_pid)
1447
return;
1448
p = expand_twiddle(DEFAULT_CTOOLZ_DIR);
1449
snprintf(pidfile, 79, "%s/pid.%s", p, nickname);
1450
if ((t = fopen(pidfile, "r")))
1451
{
1452
char buffer[80];
1453
int i;
1454
fgets(buffer, 10, t);
1455
i = atol(buffer);
1456
kill(i, SIGCHLD);
1457
if (errno != ESRCH)
1458
{
1459
fprintf(stderr, "Bitchx already running as %s\n", nickname);
1460
exit(1);
1461
}
1462
}
1463
}
1464
1465
extern int save_ipc;
1466
1467
static void remove_pid(void)
1468
{
1469
#ifdef WANT_DETACH
1470
char *p;
1471
FILE *t;
1472
if (!do_check_pid)
1473
return;
1474
p = expand_twiddle(DEFAULT_CTOOLZ_DIR);
1475
snprintf(pidfile, 79, "%s/pid.%s", p, nickname);
1476
if ((t = fopen(pidfile, "r")))
1477
{
1478
#if !defined(__EMX__) && !defined(WINNT) && !defined(GUI)
1479
SocketList *s;
1480
fclose(t);
1481
unlink(pidfile);
1482
if (save_ipc != -1 && (s = get_socket(save_ipc)))
1483
{
1484
char buf[500];
1485
sprintf(buf, s->server, s->port);
1486
unlink(buf);
1487
}
1488
#endif
1489
}
1490
#endif
1491
}
1492
1493
void setup_pid(void)
1494
{
1495
#ifdef WANT_DETACH
1496
pid_t pid;
1497
if (!do_check_pid)
1498
return;
1499
if ((pid = getpid()))
1500
{
1501
FILE *t;
1502
unlink(pidfile);
1503
if ((t = fopen(pidfile, "w")))
1504
{
1505
fprintf(t, "%u\n", pid);
1506
fclose(t);
1507
}
1508
}
1509
#endif
1510
}
1511
1512
1513
int main(int argc, char *argv[], char *envp[])
1514
{
1515
srand((unsigned)time(NULL));
1516
time(&start_time);
1517
time(&idle_time);
1518
time(&now);
1519
1520
if (munge_term_env_var())
1521
putenv("TERM=vt100");
1522
1523
/* We need to zero these early */
1524
FD_ZERO(&readables);
1525
FD_ZERO(&writables);
1526
1527
/* First thing we need to do is initialize
1528
* the global function table with the default
1529
* function pointers.
1530
*/
1531
init_global_functions();
1532
1533
/* Setup OS/2 */
1534
#if defined(__EMX__)
1535
setvbuf(stdout, NULL, _IOLBF, 80);
1536
#endif
1537
/* Setup the GUIs */
1538
#ifdef GUI
1539
gui_startup(argc, argv);
1540
#endif
1541
1542
#ifdef SOCKS
1543
SOCKSinit(argv[0]);
1544
#endif
1545
1546
#ifdef TDEBUG
1547
*cx_file = 0;
1548
cx_line = 0;
1549
*cx_function = 0;
1550
#endif
1551
1552
#if !defined(GUI)
1553
1554
printf("BitchX - Based on EPIC Software Labs epic ircII (1998).\r\n");
1555
printf("Version (%s) -- Date (%s).\r\n", irc_version, internal_version);
1556
printf("Process [%d]", getpid());
1557
if ((isatty(0) && !background) || (!isatty(0) && background))
1558
{
1559
char s[90];
1560
if (ttyname(0))
1561
{
1562
strncpy(s, ttyname(0), 85);
1563
/* printf(" connected to tty [%s]", s);*/
1564
strncpy(attach_ttyname, s, 400);
1565
}
1566
else if (background)
1567
strcpy(attach_ttyname, "tty1");
1568
}
1569
else
1570
dumb_mode = 1;
1571
printf("\n");
1572
#endif
1573
1574
1575
channel = parse_args(argv, argc, envp);
1576
check_pid();
1577
init_socketpath();
1578
1579
#ifdef WANT_TCL
1580
tcl_interp = Tcl_CreateInterp();
1581
#endif
1582
1583
if (!dumb_mode && term_init(NULL))
1584
_exit(1);
1585
1586
if (background)
1587
{
1588
#ifdef WANT_DETACH
1589
#ifndef PUBLIC_ACCESS
1590
detachcmd(NULL, NULL, NULL, NULL);
1591
#else
1592
exit(0);
1593
#endif
1594
#else
1595
fprintf(stderr, "Try compiling with WANT_DETACH\r\n");
1596
exit(0);
1597
#endif
1598
}
1599
#ifndef WANT_CORE
1600
my_signal(SIGSEGV, coredump, 0);
1601
my_signal(SIGBUS, coredump, 0);
1602
#endif
1603
my_signal(SIGQUIT, SIG_IGN, 0);
1604
#ifdef WANT_DETACH
1605
set_detach_on_hup(NULL, NULL, DEFAULT_DETACH_ON_HUP);
1606
#else
1607
my_signal(SIGHUP, irc_exit_old, 0);
1608
#endif
1609
my_signal(SIGTERM, irc_exit_old, 0);
1610
my_signal(SIGPIPE, SIG_IGN, 0);
1611
my_signal(SIGINT, cntl_c, 0);
1612
my_signal(SIGCHLD, child_reap, 0);
1613
my_signal(SIGALRM, nothing, 0);
1614
my_signal(SIGUSR1, sig_user1, 0);
1615
#ifdef GTK
1616
my_signal(SIGTTOU, SIG_IGN, 0);
1617
#endif
1618
#if 0
1619
my_signal(SIGUSR1, sigusr2, 0);
1620
my_signal(SIGUSR2, sigusr3, 0);
1621
#endif
1622
init_output();
1623
1624
if (!dumb_mode)
1625
{
1626
init_screen();
1627
if (background)
1628
{
1629
use_input = 0;
1630
main_screen->fdin = main_screen->fdout = open("/dev/null", O_RDWR|O_NOCTTY);
1631
new_open(main_screen->fdin);
1632
main_screen->fpout = fdopen(1, "w");
1633
main_screen->fpin = fdopen(0, "r");
1634
}
1635
#ifndef __EMX__
1636
my_signal(SIGCONT, term_cont, 0);
1637
#if !defined(WINNT) && !defined(GTK)
1638
my_signal(SIGWINCH, sig_refresh_screen, 0);
1639
#endif
1640
#endif
1641
1642
}
1643
else
1644
{
1645
if (background)
1646
{
1647
my_signal(SIGHUP, SIG_IGN, 0);
1648
background = 0;
1649
#ifndef WANT_DETACH
1650
term_reset();
1651
fprintf(stderr, "try recompiling the client with WANT_DETACH defined\r\n");
1652
exit(0);
1653
use_input = 0;
1654
#endif
1655
}
1656
create_new_screen();
1657
new_window(main_screen);
1658
}
1659
1660
setup_pid();
1661
init_keys();
1662
init_keys2();
1663
init_variables();
1664
init_dcc_table();
1665
1666
#if defined(THREAD) && defined(WANT_NSLOOKUP)
1667
start_dns();
1668
#endif
1669
1670
if (!dumb_mode)
1671
{
1672
build_status(current_window, NULL, 0);
1673
update_input(UPDATE_ALL);
1674
}
1675
1676
start_identd();
1677
1678
#ifdef WANT_TCL
1679
tcl_init();
1680
#ifdef WANT_TK
1681
Tk_Init(tcl_interp);
1682
#endif
1683
add_tcl_vars();
1684
#endif
1685
#ifdef HAVE_SSL
1686
{
1687
char *entropy = malloc(100);
1688
int i;
1689
1690
for(i=0;i<100;i++)
1691
entropy[i] = (char) getrandom(0, 255);
1692
1693
/* Many systems don't have /dev/random so we seed */
1694
RAND_seed(entropy, 100);
1695
SSLeay_add_ssl_algorithms();
1696
SSL_load_error_strings();
1697
free(entropy);
1698
}
1699
#endif
1700
1701
#ifdef CLOAKED
1702
initsetproctitle(argc, argv, envp);
1703
sprintf(proctitlestr, CLOAKED);
1704
setproctitle("%s", proctitlestr);
1705
#endif
1706
1707
/* We move from run level 0 to run level 1
1708
* signifying that we have completed the initial
1709
* startup and are now ready to load scripts.
1710
*/
1711
run_level = 1;
1712
1713
display_bitchx(-1);
1714
if (bflag)
1715
load_scripts();
1716
1717
#ifdef GUI
1718
gui_font_init();
1719
#endif
1720
1721
reinit_autoresponse(current_window, NULL, 0);
1722
if (auto_connect)
1723
get_connected(0, -1);
1724
else
1725
display_server_list();
1726
start_memdebug();
1727
1728
set_input(empty_string);
1729
set_input_prompt(current_window, get_string_var(INPUT_PROMPT_VAR), 0);
1730
1731
/* We now move from run level 1 to run level 2
1732
* signifying that we are in normal operation mode.
1733
*/
1734
run_level = 2;
1735
1736
for (;;)
1737
io("main");
1738
#ifdef GUI
1739
gui_exit();
1740
#else
1741
ircpanic("get_line() returned");
1742
#endif
1743
restore_term_env_var ();
1744
return (-((int)0xdead));
1745
}
1746
1747