1 /************************************************************************
2 * Unreal Internet Relay Chat Daemon, src/ircd.c
3 * Copyright (C) 1990 Jarkko Oikarinen and
4 * University of Oulu, Computing Center
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 1, or (at your option)
9 * any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20
21 #ifndef CLEAN_COMPILE
22 static char sccsid[] =
23 "@(#)ircd.c 2.48 3/9/94 (C) 1988 University of Oulu, \
24 Computing Center and Jarkko Oikarinen";
25 #endif
26
27 #include "config.h"
28 #include "struct.h"
29 #include "common.h"
30 #include "sys.h"
31 #include "numeric.h"
32 #include "msg.h"
33 #include <sys/stat.h>
34 #include <signal.h>
35 #include <fcntl.h>
36 #include <sys/types.h>
37 #ifndef _WIN32
38 #include <sys/file.h>
39 #include <pwd.h>
40 #include <grp.h>
41 #include <sys/time.h>
42 #else
43 #include <io.h>
44 #include <direct.h>
45 #endif
46 #ifdef HPUX
47 #define _KERNEL /* HPUX has the world's worst headers... */
48 #endif
49 #ifndef _WIN32
50 #include <sys/resource.h>
51 #endif
52 #ifdef HPUX
53 #undef _KERNEL
54 #endif
55 #include <errno.h>
56 #ifdef HAVE_PSSTRINGS
57 #include <sys/exec.h>
58 #endif
59 #ifdef HAVE_PSTAT
60 #include <sys/pstat.h>
61 #endif
62 #include "h.h"
63 #ifndef NO_FDLIST
64 #include "fdlist.h"
65 #endif
66 #ifdef STRIPBADWORDS
67 #include "badwords.h"
68 #endif
69 #include "version.h"
70 #include "proto.h"
71 #ifdef _WIN32
72 extern BOOL IsService;
73 #endif
74 #ifdef USE_LIBCURL
75 #include <curl/curl.h>
76 #endif
77 ID_Copyright
78 ("(C) 1988 University of Oulu, Computing Center and Jarkko Oikarinen");
79 ID_Notes("2.48 3/9/94");
80 #ifdef __FreeBSD__
81 char *malloc_options = "h" MALLOC_FLAGS_EXTRA;
82 #endif
83 time_t TSoffset = 0;
84
85 #ifndef _WIN32
86 extern char unreallogo[];
87 #endif
88 int SVSNOOP = 0;
89 extern MODVAR char *buildid;
90 time_t timeofday = 0;
91 int tainted = 0;
92 LoopStruct loop;
93 MODVAR MemoryInfo StatsZ;
94 #ifndef _WIN32
95 uid_t irc_uid = 0;
96 gid_t irc_gid = 0;
97 #endif
98
99 int R_do_dns, R_fin_dns, R_fin_dnsc, R_fail_dns, R_do_id, R_fin_id, R_fail_id;
100
101 char REPORT_DO_DNS[256], REPORT_FIN_DNS[256], REPORT_FIN_DNSC[256],
102 REPORT_FAIL_DNS[256], REPORT_DO_ID[256], REPORT_FIN_ID[256],
103 REPORT_FAIL_ID[256];
104 extern ircstats IRCstats;
105 aClient me; /* That's me */
106 MODVAR char *me_hash;
107 aClient *client = &me; /* Pointer to beginning of Client list */
108 extern char backupbuf[8192];
109 #ifdef _WIN32
110 extern void CleanUpSegv(int sig);
111 extern SERVICE_STATUS_HANDLE IRCDStatusHandle;
112 extern SERVICE_STATUS IRCDStatus;
113 #endif
114 #ifndef NO_FDLIST
115 fdlist default_fdlist;
116 fdlist busycli_fdlist;
117 fdlist serv_fdlist;
118 fdlist oper_fdlist;
119 fdlist unknown_fdlist;
120 float currentrate;
121 float currentrate2; /* outgoing */
122 float highest_rate = 0;
123 float highest_rate2 = 0;
124 int lifesux = 0;
125 int LRV = LOADRECV;
126 TS LCF = LOADCFREQ;
127 int currlife = 0;
128 int HTMLOCK = 0;
129 int noisy_htm = 1;
130 long lastrecvK = 0;
131 long lastsendK = 0;
132
133 TS check_fdlists();
134 #endif
135
136 unsigned char conf_debuglevel = 0;
137 char trouble_info[1024];
138
139 #ifdef USE_LIBCURL
140 extern void url_init(void);
141 #endif
142
143 time_t highesttimeofday=0, oldtimeofday=0, lasthighwarn=0;
144
145
save_stats(void)146 void save_stats(void)
147 {
148 FILE *stats = fopen("ircd.stats", "w");
149 if (!stats)
150 return;
151 fprintf(stats, "%i\n", IRCstats.clients);
152 fprintf(stats, "%i\n", IRCstats.invisible);
153 fprintf(stats, "%i\n", IRCstats.servers);
154 fprintf(stats, "%i\n", IRCstats.operators);
155 fprintf(stats, "%i\n", IRCstats.unknown);
156 fprintf(stats, "%i\n", IRCstats.me_clients);
157 fprintf(stats, "%i\n", IRCstats.me_servers);
158 fprintf(stats, "%i\n", IRCstats.me_max);
159 fprintf(stats, "%i\n", IRCstats.global_max);
160 fclose(stats);
161 }
162
163
164 void server_reboot(char *);
165 void restart(char *);
166 static void open_debugfile(), setup_signals();
167 extern void init_glines(void);
168 extern void tkl_init(void);
169
170 MODVAR TS last_garbage_collect = 0;
171 #ifndef _WIN32
172 MODVAR char **myargv;
173 #else
174 LPCSTR cmdLine;
175 #endif
176 int portnum = -1; /* Server port number, listening this */
177 char *configfile = CONFIGFILE; /* Server configuration file */
178 int debuglevel = 10; /* Server debug level */
179 int bootopt = 0; /* Server boot option flags */
180 char *debugmode = ""; /* -"- -"- -"- */
181 char *sbrk0; /* initial sbrk(0) */
182 static int dorehash = 0, dorestart = 0;
183 static char *dpath = DPATH;
184 MODVAR int booted = FALSE;
185 MODVAR TS nextconnect = 1; /* time for next try_connections call */
186 MODVAR TS nextping = 1; /* same as above for check_pings() */
187 MODVAR TS nextdnscheck = 0; /* next time to poll dns to force timeouts */
188 MODVAR TS nextexpire = 1; /* next expire run on the dns cache */
189 MODVAR TS lastlucheck = 0;
190
191 #ifdef UNREAL_DEBUG
192 #undef CHROOTDIR
193 #define CHROOT
194 #endif
195
196 MODVAR TS NOW;
197 #if defined(PROFIL) && !defined(_WIN32)
198 extern etext();
199
s_monitor(void)200 VOIDSIG s_monitor(void)
201 {
202 static int mon = 0;
203 #ifdef POSIX_SIGNALS
204 struct sigaction act;
205 #endif
206
207 (void)moncontrol(mon);
208 mon = 1 - mon;
209 #ifdef POSIX_SIGNALS
210 act.sa_handler = s_rehash;
211 act.sa_flags = 0;
212 (void)sigemptyset(&act.sa_mask);
213 (void)sigaddset(&act.sa_mask, SIGUSR1);
214 (void)sigaction(SIGUSR1, &act, NULL);
215 #else
216 (void)signal(SIGUSR1, s_monitor);
217 #endif
218 }
219
220 #endif
221
s_die()222 VOIDSIG s_die()
223 {
224 #ifdef _WIN32
225 int i;
226 aClient *cptr;
227 if (!IsService)
228 {
229 unload_all_modules();
230 for (i = LastSlot; i >= 0; i--)
231 if ((cptr = local[i]) && DBufLength(&cptr->sendQ) > 0)
232 (void)send_queued(cptr);
233
234 exit(-1);
235 }
236 else {
237 SERVICE_STATUS status;
238 SC_HANDLE hSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
239 SC_HANDLE hService = OpenService(hSCManager, "UnrealIRCd", SERVICE_STOP);
240 ControlService(hService, SERVICE_CONTROL_STOP, &status);
241 }
242 #else
243 unload_all_modules();
244 flush_connections(&me);
245 exit(-1);
246 #endif
247 }
248
249 #ifndef _WIN32
s_rehash()250 static VOIDSIG s_rehash()
251 #else
252 VOIDSIG s_rehash()
253 #endif
254 {
255 #ifdef POSIX_SIGNALS
256 struct sigaction act;
257 #endif
258 dorehash = 1;
259 #ifdef POSIX_SIGNALS
260 act.sa_handler = s_rehash;
261 act.sa_flags = 0;
262 (void)sigemptyset(&act.sa_mask);
263 (void)sigaddset(&act.sa_mask, SIGHUP);
264 (void)sigaction(SIGHUP, &act, NULL);
265 #else
266 # ifndef _WIN32
267 (void)signal(SIGHUP, s_rehash); /* sysV -argv */
268 # endif
269 #endif
270 }
271
restart(char * mesg)272 void restart(char *mesg)
273 {
274 server_reboot(mesg);
275 }
276
s_restart()277 VOIDSIG s_restart()
278 {
279 dorestart = 1;
280 #if 0
281 static int restarting = 0;
282
283 if (restarting == 0) {
284 /*
285 * Send (or attempt to) a dying scream to oper if present
286 */
287
288 restarting = 1;
289 server_reboot("SIGINT");
290 }
291 #endif
292 }
293
294
295 #ifndef _WIN32
dummy()296 VOIDSIG dummy()
297 {
298 #ifndef HAVE_RELIABLE_SIGNALS
299 (void)signal(SIGALRM, dummy);
300 (void)signal(SIGPIPE, dummy);
301 #ifndef HPUX /* Only 9k/800 series require this, but don't know how to.. */
302 # ifdef SIGWINCH
303 (void)signal(SIGWINCH, dummy);
304 # endif
305 #endif
306 #else
307 # ifdef POSIX_SIGNALS
308 struct sigaction act;
309
310 act.sa_handler = dummy;
311 act.sa_flags = 0;
312 (void)sigemptyset(&act.sa_mask);
313 (void)sigaddset(&act.sa_mask, SIGALRM);
314 (void)sigaddset(&act.sa_mask, SIGPIPE);
315 # ifdef SIGWINCH
316 (void)sigaddset(&act.sa_mask, SIGWINCH);
317 # endif
318 (void)sigaction(SIGALRM, &act, (struct sigaction *)NULL);
319 (void)sigaction(SIGPIPE, &act, (struct sigaction *)NULL);
320 # ifdef SIGWINCH
321 (void)sigaction(SIGWINCH, &act, (struct sigaction *)NULL);
322 # endif
323 # endif
324 #endif
325 }
326
327 #endif /* _WIN32 */
328
329
server_reboot(char * mesg)330 void server_reboot(char *mesg)
331 {
332 int i;
333 #ifdef _WIN32
334 aClient *cptr;
335 #endif
336 sendto_realops("Aieeeee!!! Restarting server... %s", mesg);
337 Debug((DEBUG_NOTICE, "Restarting server... %s", mesg));
338 #ifndef _WIN32
339 flush_connections(&me);
340 #else
341 for (i = LastSlot; i >= 0; i--)
342 if ((cptr = local[i]) && DBufLength(&cptr->sendQ) > 0)
343 (void)send_queued(cptr);
344 #endif
345 /*
346 * ** fd 0 must be 'preserved' if either the -d or -i options have
347 * ** been passed to us before restarting.
348 */
349 #ifdef HAVE_SYSLOG
350 (void)closelog();
351 #endif
352 #ifndef _WIN32
353 for (i = 3; i < MAXCONNECTIONS; i++)
354 (void)close(i);
355 if (!(bootopt & (BOOT_TTY | BOOT_DEBUG)))
356 (void)close(2);
357 (void)close(1);
358 (void)close(0);
359 (void)execv(MYNAME, myargv);
360 #else
361 close_connections();
362 if (!IsService)
363 {
364 CleanUp();
365 WinExec(cmdLine, SW_SHOWDEFAULT);
366 }
367 #endif
368 #ifndef _WIN32
369 Debug((DEBUG_FATAL, "Couldn't restart server: %s", strerror(errno)));
370 #else
371 Debug((DEBUG_FATAL, "Couldn't restart server: %s",
372 strerror(GetLastError())));
373 #endif
374 unload_all_modules();
375 #ifdef _WIN32
376 if (IsService)
377 {
378 SERVICE_STATUS status;
379 PROCESS_INFORMATION pi;
380 STARTUPINFO si;
381 char fname[MAX_PATH];
382 bzero(&status, sizeof(status));
383 bzero(&si, sizeof(si));
384 IRCDStatus.dwCurrentState = SERVICE_STOP_PENDING;
385 SetServiceStatus(IRCDStatusHandle, &IRCDStatus);
386 GetModuleFileName(GetModuleHandle(NULL), fname, MAX_PATH);
387 CreateProcess(fname, "restartsvc", NULL, NULL, FALSE,
388 0, NULL, NULL, &si, &pi);
389 IRCDStatus.dwCurrentState = SERVICE_STOPPED;
390 SetServiceStatus(IRCDStatusHandle, &IRCDStatus);
391 ExitProcess(0);
392 }
393 else
394 #endif
395 exit(-1);
396 }
397
398 MODVAR char *areason;
399
EVENT(loop_event)400 EVENT(loop_event)
401 {
402 if (loop.do_garbage_collect == 1) {
403 garbage_collect(NULL);
404 }
405 }
406
EVENT(garbage_collect)407 EVENT(garbage_collect)
408 {
409 extern int freelinks;
410 extern Link *freelink;
411 Link p;
412 int ii;
413
414 if (loop.do_garbage_collect == 1)
415 sendto_realops("Doing garbage collection ..");
416 if (freelinks > HOW_MANY_FREELINKS_ALLOWED) {
417 ii = freelinks;
418 while (freelink && (freelinks > HOW_MANY_FREELINKS_ALLOWED)) {
419 freelinks--;
420 p.next = freelink;
421 freelink = freelink->next;
422 MyFree(p.next);
423 }
424 if (loop.do_garbage_collect == 1) {
425 loop.do_garbage_collect = 0;
426 sendto_realops
427 ("Cleaned up %i garbage blocks", (ii - freelinks));
428 }
429 }
430 if (loop.do_garbage_collect == 1)
431 loop.do_garbage_collect = 0;
432 }
433
EVENT(deprecated_notice)434 EVENT(deprecated_notice)
435 {
436 /* Send a warning to opers currently online every week after November 1, 2016 */
437 if (TStime() > 1477954800)
438 {
439 sendto_realops("[WARNING] UnrealIRCd 3.2.x is no longer supported after December 31, 2016. "
440 "See https://www.unrealircd.org/docs/UnrealIRCd_3.2.x_deprecated");
441 ircd_log(LOG_ERROR, "[WARNING] UnrealIRCd 3.2.x is no longer supported after December 31, 2016. "
442 "See https://www.unrealircd.org/docs/UnrealIRCd_3.2.x_deprecated");
443 }
444 }
445
446 /*
447 ** try_connections
448 **
449 ** Scan through configuration and try new connections.
450 ** Returns the calendar time when the next call to this
451 ** function should be made latest. (No harm done if this
452 ** is called earlier or later...)
453 */
try_connections(TS currenttime)454 static TS try_connections(TS currenttime)
455 {
456 ConfigItem_link *aconf;
457 ConfigItem_deny_link *deny;
458 aClient *cptr;
459 int connecting, confrq;
460 TS next = 0;
461 ConfigItem_class *cltmp;
462
463 connecting = FALSE;
464 Debug((DEBUG_NOTICE, "Connection check at : %s",
465 myctime(currenttime)));
466 for (aconf = conf_link; aconf; aconf = (ConfigItem_link *) aconf->next) {
467 /*
468 * Also when already connecting! (update holdtimes) --SRB
469 */
470 if (!(aconf->options & CONNECT_AUTO) || (aconf->flag.temporary == 1))
471 continue;
472
473 cltmp = aconf->class;
474 /*
475 * ** Skip this entry if the use of it is still on hold until
476 * ** future. Otherwise handle this entry (and set it on hold
477 * ** until next time). Will reset only hold times, if already
478 * ** made one successfull connection... [this algorithm is
479 * ** a bit fuzzy... -- msa >;) ]
480 */
481
482 if ((aconf->hold > currenttime)) {
483 if ((next > aconf->hold) || (next == 0))
484 next = aconf->hold;
485 continue;
486 }
487
488 confrq = cltmp->connfreq;
489 aconf->hold = currenttime + confrq;
490 /*
491 * ** Found a CONNECT config with port specified, scan clients
492 * ** and see if this server is already connected?
493 */
494 cptr = find_name(aconf->servername, (aClient *)NULL);
495
496 if (!cptr && (cltmp->clients < cltmp->maxclients)) {
497 /*
498 * Check connect rules to see if we're allowed to try
499 */
500 for (deny = conf_deny_link; deny;
501 deny = (ConfigItem_deny_link *) deny->next)
502 if (!match(deny->mask, aconf->servername)
503 && crule_eval(deny->rule))
504 break;
505
506 if (!deny && connect_server(aconf, (aClient *)NULL,
507 (struct hostent *)NULL) == 0)
508 sendto_realops
509 ("Connection to %s[%s] activated.",
510 aconf->servername, aconf->hostname);
511
512 }
513 if ((next > aconf->hold) || (next == 0))
514 next = aconf->hold;
515 }
516 Debug((DEBUG_NOTICE, "Next connection check : %s", myctime(next)));
517 return (next);
518 }
519
520
521 /* Now find_kill is only called when a kline-related command is used:
522 AKILL/RAKILL/KLINE/UNKLINE/REHASH. Very significant CPU usage decrease.
523 -- Barubary */
524
525
526
check_pings(TS currenttime)527 extern TS check_pings(TS currenttime)
528 {
529 aClient *cptr = NULL;
530 ConfigItem_ban *bconf = NULL;
531 char killflag = 0;
532 int i = 0;
533 char banbuf[1024];
534 char scratch[64];
535 int ping = 0;
536
537 for (i = 0; i <= LastSlot; i++) {
538 /*
539 * If something we should not touch ..
540 */
541 if (!(cptr = local[i]) || IsMe(cptr) || IsLog(cptr))
542 continue;
543
544 /*
545 * ** Note: No need to notify opers here. It's
546 * ** already done when "FLAGS_DEADSOCKET" is set.
547 */
548 if (cptr->flags & FLAGS_DEADSOCKET) {
549 (void)exit_client(cptr, cptr, &me, cptr->error_str ? cptr->error_str : "Dead socket");
550 continue;
551 }
552 killflag = 0;
553 /*
554 * Check if user is banned
555 */
556 if (loop.do_bancheck) {
557 if (find_tkline_match(cptr, 0) < 0) {
558 /*
559 * Client exited
560 */
561 continue;
562 }
563 find_shun(cptr);
564 if (!killflag && IsPerson(cptr)) {
565 /*
566 * If it's a user, we check for CONF_BAN_USER
567 */
568 bconf =
569 Find_ban(cptr, make_user_host(cptr->
570 user ? cptr->user->username : cptr->
571 username,
572 cptr->user ? cptr->user->realhost : cptr->
573 sockhost), CONF_BAN_USER);
574 if (bconf)
575 killflag++;
576
577 if (!killflag && !IsAnOper(cptr) &&
578 (bconf =
579 Find_ban(NULL, cptr->info, CONF_BAN_REALNAME))) {
580 killflag++;
581 }
582
583 }
584 /*
585 * If no cookie, we search for Z:lines
586 */
587 if (!killflag)
588 if ((bconf =
589 Find_ban(cptr, Inet_ia2p(&cptr->ip),
590 CONF_BAN_IP)))
591 killflag++;
592 if (killflag) {
593 if (IsPerson(cptr))
594 sendto_realops("Ban active for %s (%s)",
595 get_client_name(cptr, FALSE),
596 bconf->reason ? bconf->
597 reason : "no reason");
598
599 if (IsServer(cptr))
600 sendto_realops
601 ("Ban active for server %s (%s)",
602 get_client_name(cptr, FALSE),
603 bconf->reason ? bconf->
604 reason : "no reason");
605 if (bconf->reason) {
606 if (IsPerson(cptr))
607 snprintf(banbuf, sizeof banbuf - 1,
608 "User has been banned (%s)", bconf->reason);
609 else
610 snprintf(banbuf, sizeof banbuf - 1,
611 "Banned (%s)", bconf->reason);
612 (void)exit_client(cptr, cptr, &me,
613 banbuf);
614 } else {
615 if (IsPerson(cptr))
616 (void)exit_client(cptr, cptr,
617 &me,
618 "User has been banned");
619 else
620 (void)exit_client(cptr, cptr,
621 &me, "Banned");
622 }
623 continue;
624 }
625
626 }
627 /* Do spamfilter 'user' banchecks.. */
628 if (loop.do_bancheck_spamf_user && IsPerson(cptr))
629 {
630 if (find_spamfilter_user(cptr, SPAMFLAG_NOWARN) == FLUSH_BUFFER)
631 continue;
632 }
633 if (loop.do_bancheck_spamf_away && IsPerson(cptr) && cptr->user->away)
634 {
635 if (dospamfilter(cptr, cptr->user->away, SPAMF_AWAY, NULL, SPAMFLAG_NOWARN, NULL) == FLUSH_BUFFER)
636 continue;
637 }
638 /*
639 * We go into ping phase
640 */
641 ping =
642 IsRegistered(cptr) ? (cptr->class ? cptr->
643 class->pingfreq : CONNECTTIMEOUT) : CONNECTTIMEOUT;
644 Debug((DEBUG_DEBUG, "c(%s)=%d p %d k %d a %d", cptr->name,
645 cptr->status, ping, killflag,
646 currenttime - cptr->lasttime));
647
648 /* If ping is less than or equal to the last time we received a command from them */
649 if (ping <= (currenttime - cptr->lasttime))
650 {
651 if (
652 /* If we have sent a ping */
653 ((cptr->flags & FLAGS_PINGSENT)
654 /* And they had 2x ping frequency to respond */
655 && ((currenttime - cptr->lasttime) >= (2 * ping)))
656 ||
657 /* Or isn't registered and time spent is larger than ping .. */
658 (!IsRegistered(cptr) && (currenttime - cptr->since >= ping))
659 )
660 {
661 /* if it's registered and doing dns/auth, timeout */
662 if (!IsRegistered(cptr) && (DoingDNS(cptr) || DoingAuth(cptr)))
663 {
664 if (cptr->authfd >= 0) {
665 CLOSE_SOCK(cptr->authfd);
666 --OpenFiles;
667 cptr->authfd = -1;
668 cptr->count = 0;
669 *cptr->buffer = '\0';
670 }
671 if (SHOWCONNECTINFO && !cptr->serv) {
672 if (DoingDNS(cptr))
673 sendto_one(cptr,
674 REPORT_FAIL_DNS);
675 else if (DoingAuth(cptr))
676 sendto_one(cptr,
677 REPORT_FAIL_ID);
678 }
679 Debug((DEBUG_NOTICE,
680 "DNS/AUTH timeout %s",
681 get_client_name(cptr, TRUE)));
682 unrealdns_delreq_bycptr(cptr);
683 ClearAuth(cptr);
684 ClearDNS(cptr);
685 SetAccess(cptr);
686 cptr->firsttime = currenttime;
687 cptr->lasttime = currenttime;
688 continue;
689 }
690 if (IsServer(cptr) || IsConnecting(cptr) ||
691 IsHandshake(cptr)
692 #ifdef USE_SSL
693 || IsSSLConnectHandshake(cptr)
694 #endif
695 ) {
696 sendto_realops
697 ("No response from %s, closing link",
698 get_client_name(cptr, FALSE));
699 sendto_serv_butone(&me,
700 ":%s GLOBOPS :No response from %s, closing link",
701 me.name, get_client_name(cptr,
702 FALSE));
703 }
704 #ifdef USE_SSL
705 if (IsSSLAcceptHandshake(cptr))
706 Debug((DEBUG_DEBUG, "ssl accept handshake timeout: %s (%li-%li > %li)", cptr->sockhost,
707 currenttime, cptr->since, ping));
708 #endif
709 (void)ircsprintf(scratch, "Ping timeout: %ld seconds",
710 (long) (TStime() - cptr->lasttime));
711 exit_client(cptr, cptr, &me, scratch);
712 continue;
713
714 }
715 else if (IsRegistered(cptr) &&
716 ((cptr->flags & FLAGS_PINGSENT) == 0)) {
717 /*
718 * if we havent PINGed the connection and we havent
719 * heard from it in a while, PING it to make sure
720 * it is still alive.
721 */
722 cptr->flags |= FLAGS_PINGSENT;
723 /*
724 * not nice but does the job
725 */
726 cptr->lasttime = currenttime - ping;
727 sendto_one(cptr, "%s :%s",
728 IsToken(cptr) ? TOK_PING : MSG_PING,
729 me.name);
730 }
731 }
732 /*
733 * Check UNKNOWN connections - if they have been in this state
734 * for > 100s, close them.
735 */
736 if (IsUnknown(cptr)
737 #ifdef USE_SSL
738 || (IsSSLAcceptHandshake(cptr) || IsSSLConnectHandshake(cptr))
739 #endif
740 )
741 if (cptr->firsttime ? ((currenttime - cptr->firsttime) >
742 100) : 0)
743 (void)exit_client(cptr, cptr, &me,
744 "Connection Timed Out");
745 }
746 /*
747 * EXPLANATION
748 * * on a server with a large volume of clients, at any given point
749 * * there may be a client which needs to be pinged the next second,
750 * * or even right away (a second may have passed while running
751 * * check_pings). Preserving CPU time is more important than
752 * * pinging clients out at exact times, IMO. Therefore, I am going to make
753 * * check_pings always return currenttime + 9. This means that it may take
754 * * a user up to 9 seconds more than pingfreq to timeout. Oh well.
755 * * Plus, the number is 9 to 'stagger' our check_pings calls out over
756 * * time, to avoid doing it and the other tasks ircd does at the same time
757 * * all the time (which are usually done on intervals of 5 seconds or so).
758 * * - lucas
759 * *
760 */
761 loop.do_bancheck = loop.do_bancheck_spamf_user = loop.do_bancheck_spamf_away = 0;
762 Debug((DEBUG_NOTICE, "Next check_ping() call at: %s, %d %d %d",
763 myctime(currenttime+9), ping, currenttime+9, currenttime));
764
765 return currenttime + 9;
766 }
767
768 /*
769 ** bad_command
770 ** This is called when the commandline is not acceptable.
771 ** Give error message and exit without starting anything.
772 */
bad_command(void)773 static int bad_command(void)
774 {
775 #ifndef _WIN32
776 (void)printf
777 ("Usage: ircd [-f config] [-h servername] [-p portnumber] [-x loglevel] [-t] [-H]\n");
778 (void)printf("Server not started\n\n");
779 #else
780 if (!IsService) {
781 MessageBox(NULL,
782 "Usage: wircd [-h servername] [-p portnumber] [-x loglevel]\n",
783 "UnrealIRCD/32", MB_OK);
784 }
785 #endif
786 return (-1);
787 }
788
789 char chess[] = {
790 85, 110, 114, 101, 97, 108, 0
791 };
792 #ifndef NO_FDLIST
check_fdlists(TS now)793 inline TS check_fdlists(TS now)
794 {
795 aClient *cptr;
796 int pri; /* temp. for priority */
797 int i, j;
798 j = 0;
799 for (i = LastSlot; i >= 0; i--) {
800 if (!(cptr = local[i]))
801 continue;
802 if (IsServer(cptr) || IsListening(cptr)
803 || IsOper(cptr) || DoingAuth(cptr)) {
804 busycli_fdlist.entry[++j] = i;
805 continue;
806 }
807 pri = cptr->priority;
808 if (cptr->receiveM == cptr->lastrecvM)
809 pri += 2; /* lower a bit */
810 else
811 pri -= 30;
812 if (pri < 0)
813 pri = 0;
814 if (pri > 80)
815 pri = 80;
816 cptr->lastrecvM = cptr->receiveM;
817 cptr->priority = pri;
818 if ((pri < 10) || (!lifesux && (pri < 25)))
819 busycli_fdlist.entry[++j] = i;
820 }
821 busycli_fdlist.last_entry = j; /* rest of the fdlist is garbage */
822 return (now + FDLISTCHKFREQ + lifesux * FDLISTCHKFREQ);
823 }
824
EVENT(e_check_fdlists)825 EVENT(e_check_fdlists)
826 {
827 check_fdlists(TStime());
828 }
829
830 #endif
831
version_check_logerror(char * fmt,...)832 static void version_check_logerror(char *fmt, ...)
833 {
834 va_list va;
835 char buf[1024];
836
837 va_start(va, fmt);
838 vsnprintf(buf, sizeof(buf), fmt, va);
839 va_end(va);
840 #ifndef _WIN32
841 fprintf(stderr, "[!!!] %s\n", buf);
842 #else
843 win_log("[!!!] %s", buf);
844 #endif
845 }
846
847 /** Ugly version checker that ensures zlib/ssl/curl runtime libraries match the
848 * version we compiled for.
849 */
do_version_check()850 static void do_version_check()
851 {
852 const char *compiledfor, *runtime;
853 int error = 0;
854
855 #ifdef USE_SSL
856 compiledfor = OPENSSL_VERSION_TEXT;
857 runtime = SSLeay_version(SSLEAY_VERSION);
858 if (strcasecmp(compiledfor, runtime))
859 {
860 version_check_logerror("OpenSSL version mismatch: compiled for '%s', library is '%s'",
861 compiledfor, runtime);
862 error=1;
863 }
864 #endif
865 #ifdef ZIP_LINKS
866 runtime = zlibVersion();
867 compiledfor = ZLIB_VERSION;
868 if (*compiledfor != *runtime)
869 {
870 version_check_logerror("Zlib version mismatch: compiled for '%s', library is '%s'",
871 compiledfor, runtime);
872 error = 1;
873 }
874 #endif
875 #ifdef USE_LIBCURL
876 /* Perhaps someone should tell them to do this a bit more easy ;)
877 * problem is runtime output is like: 'libcurl/7.11.1 zlib/1.2.1 c-ares/1.2.0'
878 * while header output is like: '7.11.1'.
879 */
880 {
881 char buf[128], *p;
882
883 runtime = curl_version();
884 compiledfor = LIBCURL_VERSION;
885 if (!strncmp(runtime, "libcurl/", 8))
886 {
887 strlcpy(buf, runtime+8, sizeof(buf));
888 p = strchr(buf, ' ');
889 if (p)
890 {
891 *p = '\0';
892 if (strcmp(compiledfor, buf))
893 {
894 version_check_logerror("Curl version mismatch: compiled for '%s', library is '%s'",
895 compiledfor, buf);
896 error = 1;
897 }
898 }
899 }
900 }
901 #endif
902
903 if (error)
904 {
905 #ifndef _WIN32
906 version_check_logerror("Header<->library mismatches can make UnrealIRCd *CRASH*! "
907 "Make sure you don't have multiple versions of openssl or zlib installed (eg: "
908 "one in /usr and one in /usr/local). And, if you recently upgraded them, "
909 "be sure to recompile Unreal.");
910 #else
911 version_check_logerror("Header<->library mismatches can make UnrealIRCd *CRASH*! "
912 "This should never happen with official Windows builds... unless "
913 "you overwrote any .dll files with newer/older ones or something.");
914 win_error();
915 #endif
916 tainted = 1;
917 }
918 }
919
920 extern time_t TSoffset;
921
922 extern int unreal_time_synch(int timeout);
923
924 extern MODVAR Event *events;
925 extern struct MODVAR ThrottlingBucket *ThrottlingHash[THROTTLING_HASH_SIZE+1];
926
927 /** This functions resets a couple of timers and does other things that
928 * are absolutely cruicial when the clock is adjusted - particularly
929 * when the clock goes backwards. -- Syzop
930 */
fix_timers(void)931 void fix_timers(void)
932 {
933 int i, cnt;
934 aClient *acptr;
935 Event *e;
936 struct ThrottlingBucket *n;
937 struct ThrottlingBucket z = { NULL, NULL, {0}, 0, 0};
938
939 /* Client time stuff */
940 for (i = 0; i <= LastSlot; i++)
941 {
942
943 if (!(acptr = local[i]) || IsMe(acptr))
944 continue;
945
946 /* all (servers AND users) */
947 if (MyConnect(acptr))
948 {
949 if (acptr->since > TStime())
950 {
951 Debug((DEBUG_DEBUG, "fix_timers(): %s: acptr->since %ld -> %ld",
952 acptr->name, acptr->since, TStime()));
953 acptr->since = TStime();
954 }
955 if (acptr->lasttime > TStime())
956 {
957 Debug((DEBUG_DEBUG, "fix_timers(): %s: acptr->lasttime %ld -> %ld",
958 acptr->name, acptr->lasttime, TStime()));
959 acptr->lasttime = TStime();
960 }
961 if (acptr->last > TStime())
962 {
963 Debug((DEBUG_DEBUG, "fix_timers(): %s: acptr->last %ld -> %ld",
964 acptr->name, acptr->last, TStime()));
965 acptr->last = TStime();
966 }
967 }
968
969 /* users */
970 if (MyClient(acptr))
971 {
972 if (acptr->nextnick > TStime())
973 {
974 Debug((DEBUG_DEBUG, "fix_timers(): %s: acptr->nextnick %ld -> %ld",
975 acptr->name, acptr->nextnick, TStime()));
976 acptr->nextnick = TStime();
977 }
978 if (acptr->nexttarget > TStime())
979 {
980 Debug((DEBUG_DEBUG, "fix_timers(): %s: acptr->nexttarget %ld -> %ld",
981 acptr->name, acptr->nexttarget, TStime()));
982 acptr->nexttarget = TStime();
983 }
984
985 }
986 }
987
988 /* Reset all event timers */
989 for (e = events; e; e = e->next)
990 {
991 if (e->last > TStime())
992 {
993 Debug((DEBUG_DEBUG, "fix_timers(): %s: e->last %ld -> %ld",
994 e->name, e->last, TStime()-1));
995 e->last = TStime()-1;
996 }
997 }
998
999 /* Just flush all throttle stuff... */
1000 cnt = 0;
1001 for (i = 0; i < THROTTLING_HASH_SIZE; i++)
1002 for (n = ThrottlingHash[i]; n; n = n->next)
1003 {
1004 z.next = (struct ThrottlingBucket *) DelListItem(n, ThrottlingHash[i]);
1005 cnt++;
1006 MyFree(n);
1007 n = &z;
1008 }
1009 Debug((DEBUG_DEBUG, "fix_timers(): removed %d throttling item(s)", cnt));
1010
1011 Debug((DEBUG_DEBUG, "fix_timers(): updating nextping/nextconnect/nextdnscheck/nextexpire (%ld/%ld/%ld/%ld)",
1012 nextping, nextconnect, nextdnscheck, nextexpire));
1013 nextping = nextconnect = nextdnscheck = nextexpire = 1;
1014 }
1015
1016
1017 #ifndef _WIN32
generate_cloakkeys()1018 static void generate_cloakkeys()
1019 {
1020 /* Generate 3 cloak keys */
1021 #define GENERATE_CLOAKKEY_MINLEN 16
1022 #define GENERATE_CLOAKKEY_MAXLEN 32 /* Length of cloak keys to generate. */
1023 char keyBuf[GENERATE_CLOAKKEY_MAXLEN + 1];
1024 int keyNum;
1025 int keyLen;
1026 int charIndex;
1027 int value;
1028
1029 short has_upper;
1030 short has_lower;
1031 short has_num;
1032
1033 fprintf(stderr, "Here are 3 random cloak keys:\n");
1034
1035 for (keyNum = 0; keyNum < 3; ++keyNum)
1036 {
1037 has_upper = 0;
1038 has_lower = 0;
1039 has_num = 0;
1040
1041 keyLen = (getrandom8() % (GENERATE_CLOAKKEY_MAXLEN - GENERATE_CLOAKKEY_MINLEN + 1)) + GENERATE_CLOAKKEY_MINLEN;
1042 for (charIndex = 0; charIndex < keyLen; ++charIndex)
1043 {
1044 switch (getrandom8() % 3)
1045 {
1046 case 0: /* Uppercase. */
1047 keyBuf[charIndex] = (char)('A' + (getrandom8() % ('Z' - 'A')));
1048 has_upper = 1;
1049 break;
1050 case 1: /* Lowercase. */
1051 keyBuf[charIndex] = (char)('a' + (getrandom8() % ('z' - 'a')));
1052 has_lower = 1;
1053 break;
1054 case 2: /* Digit. */
1055 keyBuf[charIndex] = (char)('0' + (getrandom8() % ('9' - '0')));
1056 has_num = 1;
1057 break;
1058 }
1059 }
1060 keyBuf[keyLen] = '\0';
1061
1062 if (has_upper && has_lower && has_num)
1063 (void)fprintf(stderr, "%s\n", keyBuf);
1064 else
1065 /* Try again. For this reason, keyNum must be signed. */
1066 keyNum--;
1067 }
1068 }
1069 #endif
1070
1071 /* MY tdiff... because 'double' sucks.
1072 * This should work until 2038, and very likely after that as well
1073 * because 'long' should be 64 bit on all systems by then... -- Syzop
1074 */
1075 #define mytdiff(a, b) ((long)a - (long)b)
1076
1077 #ifndef _WIN32
main(int argc,char * argv[])1078 int main(int argc, char *argv[])
1079 #else
1080 int InitwIRCD(int argc, char *argv[])
1081 #endif
1082 {
1083 #ifdef _WIN32
1084 WORD wVersionRequested = MAKEWORD(1, 1);
1085 WSADATA wsaData;
1086 #else
1087 uid_t uid, euid;
1088 gid_t gid, egid;
1089 TS delay = 0;
1090 struct passwd *pw;
1091 struct group *gr;
1092 #endif
1093 #ifdef HAVE_PSTAT
1094 union pstun pstats;
1095 #endif
1096 int portarg = 0;
1097 #ifdef FORCE_CORE
1098 struct rlimit corelim;
1099 #endif
1100 #ifndef NO_FDLIST
1101 TS nextfdlistcheck = 0; /*end of priority code */
1102 #endif
1103
1104 memset(&botmotd, '\0', sizeof(aMotdFile));
1105 memset(&rules, '\0', sizeof(aMotdFile));
1106 memset(&opermotd, '\0', sizeof(aMotdFile));
1107 memset(&motd, '\0', sizeof(aMotdFile));
1108 memset(&smotd, '\0', sizeof(aMotdFile));
1109 memset(&svsmotd, '\0', sizeof(aMotdFile));
1110
1111 #ifdef _WIN32
1112 CreateMutex(NULL, FALSE, "UnrealMutex");
1113 SetErrorMode(SEM_FAILCRITICALERRORS);
1114 #endif
1115 #if !defined(_WIN32) && !defined(_AMIGA)
1116 sbrk0 = (char *)sbrk((size_t)0);
1117 uid = getuid();
1118 euid = geteuid();
1119 gid = getgid();
1120 egid = getegid();
1121
1122 #ifndef IRC_USER
1123 if (!euid)
1124 {
1125 fprintf(stderr,
1126 "WARNING: You are running UnrealIRCd as root and it is not\n"
1127 " configured to drop priviliges. This is _very_ dangerous,\n"
1128 " as any compromise of your UnrealIRCd is the same as\n"
1129 " giving a cracker root SSH access to your box.\n"
1130 " You should either start UnrealIRCd under a different\n"
1131 " account than root, or set IRC_USER in include/config.h\n"
1132 " to a nonprivileged username and recompile.\n");
1133 }
1134 #endif /* IRC_USER */
1135
1136 # ifdef PROFIL
1137 (void)monstartup(0, etext);
1138 (void)moncontrol(1);
1139 (void)signal(SIGUSR1, s_monitor);
1140 # endif
1141 #endif
1142 #if defined(IRC_USER) && defined(IRC_GROUP)
1143 if ((int)getuid() == 0) {
1144
1145 pw = getpwnam(IRC_USER);
1146 gr = getgrnam(IRC_GROUP);
1147
1148 if ((pw == NULL) || (gr == NULL)) {
1149 fprintf(stderr, "ERROR: Unable to lookup to specified user (IRC_USER) or group (IRC_GROUP): %s\n", strerror(errno));
1150 exit(-1);
1151 } else {
1152 irc_uid = pw->pw_uid;
1153 irc_gid = gr->gr_gid;
1154 }
1155 }
1156 #endif
1157 #ifdef CHROOTDIR
1158 if (chdir(dpath)) {
1159 perror("chdir");
1160 fprintf(stderr, "ERROR: Unable to change to directory '%s'\n", dpath);
1161 exit(-1);
1162 }
1163 if (geteuid() != 0)
1164 fprintf(stderr, "WARNING: IRCd compiled with CHROOTDIR but effective user id is not root!? "
1165 "Booting is very likely to fail...\n");
1166 init_resolver(1);
1167 {
1168 struct stat sb;
1169 mode_t umaskold;
1170
1171 umaskold = umask(0);
1172 if (mkdir("dev", S_IRUSR|S_IWUSR|S_IXUSR|S_IXGRP|S_IXOTH) != 0 && errno != EEXIST)
1173 {
1174 fprintf(stderr, "ERROR: Cannot mkdir dev: %s\n", strerror(errno));
1175 exit(5);
1176 }
1177 if (stat("/dev/urandom", &sb) != 0)
1178 {
1179 fprintf(stderr, "ERROR: Cannot stat /dev/urandom: %s\n", strerror(errno));
1180 exit(5);
1181 }
1182 if (mknod("dev/urandom", sb.st_mode, sb.st_rdev) != 0 && errno != EEXIST)
1183 {
1184 fprintf(stderr, "ERROR: Cannot mknod dev/urandom: %s\n", strerror(errno));
1185 exit(5);
1186 }
1187 if (stat("/dev/null", &sb) != 0)
1188 {
1189 fprintf(stderr, "ERROR: Cannot stat /dev/null: %s\n", strerror(errno));
1190 exit(5);
1191 }
1192 if (mknod("dev/null", sb.st_mode, sb.st_rdev) != 0 && errno != EEXIST)
1193 {
1194 fprintf(stderr, "ERROR: Cannot mknod dev/null: %s\n", strerror(errno));
1195 exit(5);
1196 }
1197 if (stat("/dev/tty", &sb) != 0)
1198 {
1199 fprintf(stderr, "ERROR: Cannot stat /dev/tty: %s\n", strerror(errno));
1200 exit(5);
1201 }
1202 if (mknod("dev/tty", sb.st_mode, sb.st_rdev) != 0 && errno != EEXIST)
1203 {
1204 fprintf(stderr, "ERROR: Cannot mknod dev/tty: %s\n", strerror(errno));
1205 exit(5);
1206 }
1207 umask(umaskold);
1208 }
1209 if (chroot(DPATH)) {
1210 (void)fprintf(stderr, "ERROR: Cannot (chdir/)chroot to directory '%s'\n", dpath);
1211 exit(5);
1212 }
1213 #endif /*CHROOTDIR*/
1214 #ifndef _WIN32
1215 myargv = argv;
1216 #else
1217 cmdLine = GetCommandLine();
1218 #endif
1219 #ifndef _WIN32
1220 (void)umask(077); /* better safe than sorry --SRB */
1221 #else
1222 WSAStartup(wVersionRequested, &wsaData);
1223 #endif
1224 bzero((char *)&me, sizeof(me));
1225 bzero(&StatsZ, sizeof(StatsZ));
1226 setup_signals();
1227 charsys_reset();
1228 init_ircstats();
1229 #ifdef USE_LIBCURL
1230 url_init();
1231 #endif
1232 tkl_init();
1233 umode_init();
1234 #ifdef EXTCMODE
1235 extcmode_init();
1236 #endif
1237 extban_init();
1238 init_random(); /* needs to be done very early!! */
1239 clear_scache_hash_table();
1240 #ifdef FORCE_CORE
1241 corelim.rlim_cur = corelim.rlim_max = RLIM_INFINITY;
1242 if (setrlimit(RLIMIT_CORE, &corelim))
1243 printf("unlimit core size failed; errno = %d\n", errno);
1244 #endif
1245 /*
1246 * ** All command line parameters have the syntax "-fstring"
1247 * ** or "-f string" (e.g. the space is optional). String may
1248 * ** be empty. Flag characters cannot be concatenated (like
1249 * ** "-fxyz"), it would conflict with the form "-fstring".
1250 */
1251 while (--argc > 0 && (*++argv)[0] == '-') {
1252 char *p = argv[0] + 1;
1253 int flag = *p++;
1254 if (flag == '\0' || *p == '\0') {
1255 if (argc > 1 && argv[1][0] != '-') {
1256 p = *++argv;
1257 argc -= 1;
1258 } else
1259 p = "";
1260 }
1261 switch (flag) {
1262 #ifndef _WIN32
1263 case 'a':
1264 bootopt |= BOOT_AUTODIE;
1265 break;
1266 case 'c':
1267 bootopt |= BOOT_CONSOLE;
1268 break;
1269 case 'q':
1270 bootopt |= BOOT_QUICK;
1271 break;
1272 case 'd':
1273 (void)setuid((uid_t) uid);
1274 #else
1275 case 'd':
1276 #endif
1277 dpath = p;
1278 break;
1279 case 'F':
1280 bootopt |= BOOT_NOFORK;
1281 break;
1282 #ifndef _WIN32
1283 case 'f':
1284 #ifndef CMDLINE_CONFIG
1285 if ((uid == euid) && (gid == egid))
1286 configfile = p;
1287 else
1288 printf("ERROR: Command line config with a setuid/setgid ircd is not allowed");
1289 #else
1290 (void)setuid((uid_t) uid);
1291 configfile = p;
1292 #endif
1293 break;
1294 case 'h':
1295 if (!strchr(p, '.')) {
1296
1297 (void)printf
1298 ("ERROR: %s is not valid: Server names must contain at least 1 \".\"\n",
1299 p);
1300 exit(1);
1301 }
1302 strncpyzt(me.name, p, sizeof(me.name));
1303 break;
1304 #endif
1305 #ifndef _WIN32
1306 case 'P':{
1307 short type;
1308 char *result;
1309 srandom(TStime());
1310 if ((type = Auth_FindType(p)) == -1) {
1311 printf("No such auth type %s\n", p);
1312 exit(0);
1313 }
1314 p = *++argv;
1315 argc--;
1316 #ifdef AUTHENABLE_UNIXCRYPT
1317 if ((type == AUTHTYPE_UNIXCRYPT) && (strlen(p) > 8))
1318 {
1319 printf("WARNING: Password truncated to 8 characters due to 'crypt' algorithm. "
1320 "You are suggested to use the 'md5' algorithm instead.");
1321 p[8] = '\0';
1322 }
1323 #endif
1324 if (!(result = Auth_Make(type, p))) {
1325 printf("Authentication failed\n");
1326 exit(0);
1327 }
1328 printf("Encrypted password is: %s\n", result);
1329 exit(0);
1330 }
1331 #endif
1332
1333 case 'p':
1334 if ((portarg = atoi(p)) > 0)
1335 portnum = portarg;
1336 break;
1337 case 's':
1338 (void)printf("sizeof(aClient) == %ld\n",
1339 (long)sizeof(aClient));
1340 (void)printf("sizeof(aChannel) == %ld\n",
1341 (long)sizeof(aChannel));
1342 (void)printf("sizeof(aServer) == %ld\n",
1343 (long)sizeof(aServer));
1344 (void)printf("sizeof(Link) == %ld\n",
1345 (long)sizeof(Link));
1346 (void)printf("sizeof(anUser) == %ld\n",
1347 (long)sizeof(anUser));
1348 (void)printf("sizeof(aTKline) == %ld\n",
1349 (long)sizeof(aTKline));
1350 (void)printf("sizeof(struct ircstatsx) == %ld\n",
1351 (long)sizeof(struct ircstatsx));
1352 (void)printf("aClient remote == %ld\n",
1353 (long)CLIENT_REMOTE_SIZE);
1354 exit(0);
1355 break;
1356 #ifndef _WIN32
1357 case 't':
1358 (void)setuid((uid_t) uid);
1359 bootopt |= BOOT_TTY;
1360 break;
1361 case 'v':
1362 (void)printf("%s build %s\n", version, buildid);
1363 #else
1364 case 'v':
1365 if (!IsService) {
1366 MessageBox(NULL, version,
1367 "UnrealIRCD/Win32 version", MB_OK);
1368 }
1369 #endif
1370 exit(0);
1371 case 'C':
1372 config_verbose = atoi(p);
1373 break;
1374 case 'x':
1375 #ifdef DEBUGMODE
1376 # ifndef _WIN32
1377 (void)setuid((uid_t) uid);
1378 # endif
1379 debuglevel = atoi(p);
1380 debugmode = *p ? p : "0";
1381 bootopt |= BOOT_DEBUG;
1382 break;
1383 #else
1384 # ifndef _WIN32
1385 (void)fprintf(stderr,
1386 "%s: DEBUGMODE must be defined for -x y\n",
1387 myargv[0]);
1388 # else
1389 if (!IsService) {
1390 MessageBox(NULL,
1391 "DEBUGMODE must be defined for -x option",
1392 "UnrealIRCD/32", MB_OK);
1393 }
1394 # endif
1395 exit(0);
1396 #endif
1397 #ifndef _WIN32
1398 case 'k':
1399 generate_cloakkeys();
1400 exit(0);
1401 #endif
1402 default:
1403 return bad_command();
1404 break;
1405 }
1406 }
1407
1408 do_version_check();
1409
1410 #ifndef CHROOTDIR
1411 if (chdir(dpath)) {
1412 # ifndef _WIN32
1413 perror("chdir");
1414 fprintf(stderr, "ERROR: Unable to change to directory '%s'\n", dpath);
1415 # else
1416 if (!IsService) {
1417 MessageBox(NULL, strerror(GetLastError()),
1418 "UnrealIRCD/32: chdir()", MB_OK);
1419 }
1420 # endif
1421 exit(-1);
1422 }
1423 #endif
1424 #ifndef _WIN32
1425 mkdir("/var/run/ircd/tmp", S_IRUSR|S_IWUSR|S_IXUSR); /* Create the tmp dir, if it doesn't exist */
1426 #if defined(USE_LIBCURL) && defined(REMOTEINC_SPECIALCACHE)
1427 mkdir("cache", S_IRUSR|S_IWUSR|S_IXUSR); /* Create the cache dir, if using curl and it doesn't exist */
1428 #endif
1429 #else
1430 mkdir("/var/run/ircd/tmp");
1431 #if defined(USE_LIBCURL) && defined(REMOTEINC_SPECIALCACHE)
1432 mkdir("cache");
1433 #endif
1434 #endif
1435 #ifndef _WIN32
1436 /*
1437 * didn't set debuglevel
1438 */
1439 /*
1440 * but asked for debugging output to tty
1441 */
1442 if ((debuglevel < 0) && (bootopt & BOOT_TTY)) {
1443 (void)fprintf(stderr,
1444 "you specified -t without -x. use -x <n>\n");
1445 exit(-1);
1446 }
1447 #endif
1448
1449 /* HACK! This ifndef should be removed when the restart-on-w32-brings-up-dialog bug
1450 * is fixed. This is just an ugly "ignore the invalid parameter" thing ;). -- Syzop
1451 */
1452 #ifndef _WIN32
1453 if (argc > 0)
1454 return bad_command(); /* This should exit out */
1455 #endif
1456 #ifndef _WIN32
1457 fprintf(stderr, "%s", unreallogo);
1458 fprintf(stderr, " v%s\n", VERSIONONLY);
1459 fprintf(stderr, " using %s\n", tre_version());
1460 #ifdef USE_SSL
1461 fprintf(stderr, " using %s\n", SSLeay_version(SSLEAY_VERSION));
1462 #endif
1463 #ifdef ZIP_LINKS
1464 fprintf(stderr, " using zlib %s\n", zlibVersion());
1465 #endif
1466 #ifdef USE_LIBCURL
1467 fprintf(stderr, " using %s\n", curl_version());
1468 #endif
1469 fprintf(stderr, "\n");
1470 #endif
1471 clear_client_hash_table();
1472 clear_channel_hash_table();
1473 clear_watch_hash_table();
1474 bzero(&loop, sizeof(loop));
1475 init_CommandHash();
1476 initlists();
1477 initwhowas();
1478 initstats();
1479 DeleteTempModules();
1480 booted = FALSE;
1481 /* Hack to stop people from being able to read the config file */
1482 #if !defined(_WIN32) && !defined(_AMIGA) && !defined(OSXTIGER) && DEFAULT_PERMISSIONS != 0
1483 chmod(CPATH, DEFAULT_PERMISSIONS);
1484 #endif
1485 init_dynconf();
1486 #ifdef STATIC_LINKING
1487 {
1488 ModuleInfo ModCoreInfo;
1489 ModCoreInfo.size = sizeof(ModuleInfo);
1490 ModCoreInfo.module_load = 0;
1491 ModCoreInfo.handle = NULL;
1492 l_commands_Test(&ModCoreInfo);
1493 }
1494 #endif
1495 /*
1496 * Add default class
1497 */
1498 default_class =
1499 (ConfigItem_class *) MyMallocEx(sizeof(ConfigItem_class));
1500 default_class->flag.permanent = 1;
1501 default_class->pingfreq = PINGFREQUENCY;
1502 default_class->maxclients = 100;
1503 default_class->sendq = MAXSENDQLENGTH;
1504 default_class->name = "default";
1505 AddListItem(default_class, conf_class);
1506 if (init_conf(configfile, 0) < 0)
1507 {
1508 exit(-1);
1509 }
1510 booted = TRUE;
1511 load_tunefile();
1512 make_umodestr();
1513 make_cmodestr();
1514 #ifdef EXTCMODE
1515 make_extcmodestr();
1516 #endif
1517 make_extbanstr();
1518 isupport_init();
1519 if (!find_Command_simple("AWAY") /*|| !find_Command_simple("KILL") ||
1520 !find_Command_simple("OPER") || !find_Command_simple("PING")*/)
1521 {
1522 config_error("Someone forgot to load modules with proper commands in them. READ THE DOCUMENTATION");
1523 #ifdef _WIN32
1524 /* Temporary! */
1525 config_error("As of Unreal3.2.1 modules are supported on windows, "
1526 "therefore you MUST load the commands.dll module and a cloaking module. "
1527 "Just add 'loadmodule \"modules/commands.dll\"' and 'loadmodule \"modules/cloak.dll\"' "
1528 "to your unrealircd.conf and be sure to read the release notes!");
1529 win_error();
1530 #endif
1531 exit(-4);
1532 }
1533
1534 #ifdef USE_SSL
1535 #ifndef _WIN32
1536 fprintf(stderr, "* Initializing SSL.\n");
1537 #endif
1538 init_ssl();
1539 #endif
1540 #ifndef _WIN32
1541 fprintf(stderr,
1542 "* Dynamic configuration initialized .. booting IRCd.\n");
1543 fprintf(stderr,
1544 "---------------------------------------------------------------------\n");
1545 #endif
1546 if (time(NULL) > 1459461600)
1547 {
1548 fprintf(stderr, "WARNING: UnrealIRCd 3.2.x is no longer supported after December 31, 2016.\n"
1549 "See https://www.unrealircd.org/docs/UnrealIRCd_3.2.x_deprecated\n");
1550 }
1551 open_debugfile();
1552 #ifndef NO_FDLIST
1553 init_fdlist(&serv_fdlist);
1554 init_fdlist(&busycli_fdlist);
1555 init_fdlist(&default_fdlist);
1556 init_fdlist(&oper_fdlist);
1557 init_fdlist(&unknown_fdlist);
1558 {
1559 int i;
1560 for (i = MAXCONNECTIONS + 1; i > 0; i--)
1561 default_fdlist.entry[i] = i;
1562 }
1563 #endif
1564 if (portnum < 0)
1565 portnum = PORTNUM;
1566 me.port = portnum;
1567 (void)init_sys();
1568 me.flags = FLAGS_LISTEN;
1569 me.fd = -1;
1570 SetMe(&me);
1571 make_server(&me);
1572 #ifdef HAVE_SYSLOG
1573 openlog("ircd", LOG_PID | LOG_NDELAY, LOG_DAEMON);
1574 #endif
1575 /*
1576 * Put in our info
1577 */
1578 strncpyzt(me.info, conf_me->info, sizeof(me.info));
1579 strncpyzt(me.name, conf_me->name, sizeof(me.name));
1580 /*
1581 * We accept the first listen record
1582 */
1583 portnum = conf_listen->port;
1584 /*
1585 * This is completely unneeded-Sts
1586 me.ip.S_ADDR =
1587 *conf_listen->ip != '*' ? inet_addr(conf_listen->ip) : INADDR_ANY;
1588 */
1589 Debug((DEBUG_ERROR, "Port = %d", portnum));
1590 if (inetport(&me, conf_listen->ip, portnum))
1591 exit(1);
1592 set_non_blocking(me.fd, &me);
1593 conf_listen->options |= LISTENER_BOUND;
1594 me.umodes = conf_listen->options;
1595 conf_listen->listener = &me;
1596 run_configuration();
1597 ircd_log(LOG_ERROR, "UnrealIRCd started.");
1598
1599 read_motd(conf_files->botmotd_file, &botmotd);
1600 read_motd(conf_files->rules_file, &rules);
1601 read_motd(conf_files->opermotd_file, &opermotd);
1602 read_motd(conf_files->motd_file, &motd);
1603 read_motd(conf_files->smotd_file, &smotd);
1604 read_motd(conf_files->svsmotd_file, &svsmotd);
1605
1606 strncpy(me.sockhost, conf_listen->ip, sizeof(me.sockhost) - 1);
1607 if (me.name[0] == '\0')
1608 strncpyzt(me.name, me.sockhost, sizeof(me.name));
1609 me.hopcount = 0;
1610 me.authfd = -1;
1611 me.next = NULL;
1612 me.user = NULL;
1613 me.from = &me;
1614 me.class = (ConfigItem_class *) conf_listen;
1615 /*
1616 * This listener will never go away
1617 */
1618 conf_listen->clients++;
1619 me_hash = find_or_add(me.name);
1620 me.serv->up = me_hash;
1621 me.serv->numeric = conf_me->numeric;
1622 add_server_to_table(&me);
1623 timeofday = time(NULL);
1624 me.lasttime = me.since = me.firsttime = TStime();
1625 (void)add_to_client_hash_table(me.name, &me);
1626 #if !defined(_AMIGA) && !defined(_WIN32) && !defined(NO_FORKING)
1627 if (!(bootopt & BOOT_NOFORK))
1628 if (fork())
1629 exit(0);
1630 #endif
1631 (void)ircsprintf(REPORT_DO_DNS, ":%s %s", me.name, BREPORT_DO_DNS);
1632 (void)ircsprintf(REPORT_FIN_DNS, ":%s %s", me.name, BREPORT_FIN_DNS);
1633 (void)ircsprintf(REPORT_FIN_DNSC, ":%s %s", me.name, BREPORT_FIN_DNSC);
1634 (void)ircsprintf(REPORT_FAIL_DNS, ":%s %s", me.name, BREPORT_FAIL_DNS);
1635 (void)ircsprintf(REPORT_DO_ID, ":%s %s", me.name, BREPORT_DO_ID);
1636 (void)ircsprintf(REPORT_FIN_ID, ":%s %s", me.name, BREPORT_FIN_ID);
1637 (void)ircsprintf(REPORT_FAIL_ID, ":%s %s", me.name, BREPORT_FAIL_ID);
1638 R_do_dns = strlen(REPORT_DO_DNS);
1639 R_fin_dns = strlen(REPORT_FIN_DNS);
1640 R_fin_dnsc = strlen(REPORT_FIN_DNSC);
1641 R_fail_dns = strlen(REPORT_FAIL_DNS);
1642 R_do_id = strlen(REPORT_DO_ID);
1643 R_fin_id = strlen(REPORT_FIN_ID);
1644 R_fail_id = strlen(REPORT_FAIL_ID);
1645
1646 #if !defined(IRC_USER) && !defined(_WIN32)
1647 if ((uid != euid) && !euid) {
1648 (void)fprintf(stderr,
1649 "ERROR: do not run ircd setuid root. Make it setuid a normal user.\n");
1650 exit(-1);
1651 }
1652 #endif
1653
1654 #if defined(IRC_USER) && defined(IRC_GROUP)
1655 if ((int)getuid() == 0) {
1656 /* NOTE: irc_uid/irc_gid have been looked up earlier, before the chrooting code */
1657
1658 if ((irc_uid == 0) || (irc_gid == 0)) {
1659 (void)fprintf(stderr,
1660 "ERROR: SETUID and SETGID have not been set properly"
1661 "\nPlease read your documentation\n(HINT: IRC_USER and IRC_GROUP in include/config.h cannot be root/wheel)\n");
1662 exit(-1);
1663 } else {
1664 /*
1665 * run as a specified user
1666 */
1667
1668 (void)fprintf(stderr, "WARNING: ircd invoked as root\n");
1669 (void)fprintf(stderr, " changing to uid %d\n", irc_uid);
1670 (void)fprintf(stderr, " changing to gid %d\n", irc_gid);
1671 if (setgid(irc_gid))
1672 {
1673 fprintf(stderr, "ERROR: Unable to change group: %s\n", strerror(errno));
1674 exit(-1);
1675 }
1676 if (setuid(irc_uid))
1677 {
1678 fprintf(stderr, "ERROR: Unable to change userid: %s\n", strerror(errno));
1679 exit(-1);
1680 }
1681 }
1682 }
1683 #endif
1684 if (TIMESYNCH)
1685 {
1686 if (!unreal_time_synch(TIMESYNCH_TIMEOUT))
1687 ircd_log(LOG_ERROR, "TIME SYNCH: Unable to synchronize time: %s. "
1688 "This means UnrealIRCd was unable to synchronize the IRCd clock to a known good time source. "
1689 "As long as the server owner keeps the server clock synchronized through NTP, everything will be fine.",
1690 unreal_time_synch_error());
1691 }
1692 fix_timers(); /* Fix timers AFTER reading tune file AND timesynch */
1693 write_pidfile();
1694 Debug((DEBUG_NOTICE, "Server ready..."));
1695 SetupEvents();
1696 #ifdef THROTTLING
1697 init_throttling_hash();
1698 #endif
1699 #ifdef NEWCHFLOODPROT
1700 init_modef();
1701 #endif
1702 loop.do_bancheck = 0;
1703 loop.ircd_booted = 1;
1704 #if defined(HAVE_SETPROCTITLE)
1705 setproctitle("%s", me.name);
1706 #elif defined(HAVE_PSTAT)
1707 pstats.pst_command = me.name;
1708 pstat(PSTAT_SETCMD, pstats, strlen(me.name), 0, 0);
1709 #elif defined(HAVE_PSSTRINGS)
1710 PS_STRINGS->ps_nargvstr = 1;
1711 PS_STRINGS->ps_argvstr = me.name;
1712 #endif
1713 module_loadall(0);
1714 #ifdef STATIC_LINKING
1715 l_commands_Load(0);
1716 #endif
1717
1718 #ifndef NO_FDLIST
1719 check_fdlists(TStime());
1720 #endif
1721
1722 #ifdef _WIN32
1723 return 1;
1724 }
1725
1726
SocketLoop(void * dummy)1727 void SocketLoop(void *dummy)
1728 {
1729 TS delay = 0;
1730 static TS lastglinecheck = 0;
1731 TS last_tune;
1732 #ifndef NO_FDLIST
1733 TS nextfdlistcheck = 0; /*end of priority code */
1734 #endif
1735
1736
1737 while (1)
1738 #else
1739 nextping = timeofday;
1740 /*
1741 * Forever drunk .. forever drunk ..
1742 * * (Sorry Alphaville.)
1743 */
1744 for (;;)
1745 #endif
1746 {
1747
1748 #define NEGATIVE_SHIFT_WARN -15
1749 #define POSITIVE_SHIFT_WARN 20
1750
1751 timeofday = time(NULL) + TSoffset;
1752 if (oldtimeofday == 0)
1753 oldtimeofday = timeofday; /* pretend everything is ok the first time.. */
1754 if (mytdiff(timeofday, oldtimeofday) < NEGATIVE_SHIFT_WARN) {
1755 /* tdiff = # of seconds of time set backwards (positive number! eg: 60) */
1756 long tdiff = oldtimeofday - timeofday;
1757 ircd_log(LOG_ERROR, "WARNING: Time running backwards! Clock set back ~%ld seconds (%ld -> %ld)",
1758 tdiff, oldtimeofday, timeofday);
1759 ircd_log(LOG_ERROR, "[TimeShift] Resetting a few timers to prevent IRCd freeze!");
1760 sendto_realops("WARNING: Time running backwards! Clock set back ~%ld seconds (%ld -> %ld)",
1761 tdiff, oldtimeofday, timeofday);
1762 sendto_realops("Incorrect time for IRC servers is a serious problem. "
1763 "Time being set backwards (either by TSCTL or by resetting the clock) is "
1764 "even more serious and can cause clients to freeze, channels to be "
1765 "taken over, and other issues.");
1766 sendto_realops("Please be sure your clock is always synchronized before "
1767 "the IRCd is started or use the built-in timesynch feature.");
1768 sendto_realops("[TimeShift] Resetting a few timers to prevent IRCd freeze!");
1769 fix_timers();
1770 nextfdlistcheck = 0;
1771 } else
1772 if (mytdiff(timeofday, oldtimeofday) > POSITIVE_SHIFT_WARN) /* do not set too low or you get false positives */
1773 {
1774 /* tdiff = # of seconds of time set forward (eg: 60) */
1775 long tdiff = timeofday - oldtimeofday;
1776 ircd_log(LOG_ERROR, "WARNING: Time jumped ~%ld seconds ahead! (%ld -> %ld)",
1777 tdiff, oldtimeofday, timeofday);
1778 ircd_log(LOG_ERROR, "[TimeShift] Resetting some timers!");
1779 sendto_realops("WARNING: Time jumped ~%ld seconds ahead! (%ld -> %ld)",
1780 tdiff, oldtimeofday, timeofday);
1781 sendto_realops("Incorrect time for IRC servers is a serious problem. "
1782 "Time being adjusted (either by TSCTL or by resetting the clock) "
1783 "more than a few seconds forward/backward can lead to serious issues.");
1784 sendto_realops("Please be sure your clock is always synchronized before "
1785 "the IRCd is started or use the built-in timesynch feature.");
1786 sendto_realops("[TimeShift] Resetting some timers!");
1787 fix_timers();
1788 nextfdlistcheck = 0;
1789 }
1790 if (highesttimeofday+NEGATIVE_SHIFT_WARN > timeofday)
1791 {
1792 if (lasthighwarn > timeofday)
1793 lasthighwarn = timeofday;
1794 if (timeofday - lasthighwarn > 300)
1795 {
1796 ircd_log(LOG_ERROR, "[TimeShift] The (IRCd) clock was set backwards. "
1797 "Waiting for time to be OK again. This will be in %ld seconds",
1798 highesttimeofday - timeofday);
1799 sendto_realops("[TimeShift] The (IRCd) clock was set backwards. Timers, nick- "
1800 "and channel-timestamps are possibly incorrect. This message will "
1801 "repeat itself until we catch up with the original time, which will be "
1802 "in %ld seconds", highesttimeofday - timeofday);
1803 lasthighwarn = timeofday;
1804 }
1805 } else {
1806 highesttimeofday = timeofday;
1807 }
1808 oldtimeofday = timeofday;
1809 LockEventSystem();
1810 DoEvents();
1811 UnlockEventSystem();
1812 /*
1813 * ** Run through the hashes and check lusers every
1814 * ** second
1815 * ** also check for expiring glines
1816 */
1817
1818 #ifndef NO_FDLIST
1819 lastrecvK = me.receiveK;
1820 lastsendK = me.sendK;
1821 #endif
1822 if (IRCstats.clients > IRCstats.global_max)
1823 IRCstats.global_max = IRCstats.clients;
1824 if (IRCstats.me_clients > IRCstats.me_max)
1825 IRCstats.me_max = IRCstats.me_clients;
1826 /*
1827 * ** We only want to connect if a connection is due,
1828 * ** not every time through. Note, if there are no
1829 * ** active C lines, this call to Tryconnections is
1830 * ** made once only; it will return 0. - avalon
1831 */
1832 if (nextconnect && timeofday >= nextconnect)
1833 nextconnect = try_connections(timeofday);
1834
1835 /*
1836 * ** take the smaller of the two 'timed' event times as
1837 * ** the time of next event (stops us being late :) - avalon
1838 * ** WARNING - nextconnect can return 0!
1839 */
1840 if (nextconnect)
1841 delay = MIN(nextping, nextconnect);
1842 else
1843 delay = nextping;
1844 delay = MIN(nextdnscheck, delay);
1845 delay = MIN(nextexpire, delay);
1846 delay -= timeofday;
1847 /*
1848 * ** Adjust delay to something reasonable [ad hoc values]
1849 * ** (one might think something more clever here... --msa)
1850 * ** We don't really need to check that often and as long
1851 * ** as we don't delay too long, everything should be ok.
1852 * ** waiting too long can cause things to timeout...
1853 * ** i.e. PINGS -> a disconnection :(
1854 * ** - avalon
1855 */
1856 if (delay < 1)
1857 delay = 1;
1858 else
1859 delay = MIN(delay, TIMESEC);
1860 #ifdef NO_FDLIST
1861 (void)read_message(delay);
1862 timeofday = time(NULL) + TSoffset;
1863 #else
1864 (void)read_message(0, &serv_fdlist); /* servers */
1865 (void)read_message(1, &busycli_fdlist); /* busy clients */
1866 if (lifesux) {
1867 static time_t alllasttime = 0;
1868
1869 (void)read_message(1, &serv_fdlist);
1870 /*
1871 * read servs more often
1872 */
1873 if (lifesux > 9) { /* life really sucks */
1874 (void)read_message(1, &busycli_fdlist);
1875 (void)read_message(1, &serv_fdlist);
1876 }
1877 flush_fdlist_connections(&serv_fdlist);
1878 timeofday = time(NULL) + TSoffset;
1879 if ((alllasttime + (lifesux + 1)) < timeofday) {
1880 read_message(delay, NULL); /* check everything */
1881 alllasttime = timeofday;
1882 }
1883 } else {
1884 read_message(delay, NULL); /* check everything */
1885 timeofday = time(NULL) + TSoffset;
1886 }
1887
1888 #endif
1889 /*
1890 * Debug((DEBUG_DEBUG, "Got message(s)"));
1891 */
1892 /*
1893 * ** ...perhaps should not do these loops every time,
1894 * ** but only if there is some chance of something
1895 * ** happening (but, note that conf->hold times may
1896 * ** be changed elsewhere--so precomputed next event
1897 * ** time might be too far away... (similarly with
1898 * ** ping times) --msa
1899 */
1900 #ifdef NO_FDLIST
1901 if (timeofday >= nextping || loop.do_bancheck)
1902 #else
1903 if ((timeofday >= nextping && !lifesux) || loop.do_bancheck)
1904 #endif
1905 nextping = check_pings(timeofday);
1906 if (dorehash)
1907 {
1908 (void)rehash(&me, &me, 1);
1909 dorehash = 0;
1910 }
1911 if (dorestart)
1912 {
1913 server_reboot("SIGINT");
1914 }
1915
1916 /*
1917 * ** Flush output buffers on all connections timeofday if they
1918 * ** have data in them (or at least try to flush)
1919 * ** -avalon
1920 */
1921
1922 #ifndef NO_FDLIST
1923 /*
1924 * check which clients are active
1925 */
1926 if (timeofday > nextfdlistcheck)
1927 nextfdlistcheck = check_fdlists(timeofday);
1928 #endif
1929 flush_connections(&me);
1930
1931 /* ThA UnReAl TrOuBlE RePoRtInG SyStEm!!! */
1932 if (trouble_info[0] != '\0')
1933 {
1934 sendto_realops("*** TROUBLE: %s ***", trouble_info);
1935 ircd_log(LOG_ERROR, "TROUBLE: %s", trouble_info);
1936 trouble_info[0] = '\0';
1937 }
1938 }
1939 }
1940
1941 /*
1942 * open_debugfile
1943 *
1944 * If the -t option is not given on the command line when the server is
1945 * started, all debugging output is sent to the file set by LPATH in config.h
1946 * Here we just open that file and make sure it is opened to fd 2 so that
1947 * any fprintf's to stderr also goto the logfile. If the debuglevel is not
1948 * set from the command line by -x, use /dev/null as the dummy logfile as long
1949 * as DEBUGMODE has been defined, else dont waste the fd.
1950 */
open_debugfile(void)1951 static void open_debugfile(void)
1952 {
1953 #ifdef DEBUGMODE
1954 int fd;
1955 aClient *cptr;
1956 if (debuglevel >= 0) {
1957 cptr = make_client(NULL, NULL);
1958 cptr->fd = 2;
1959 SetLog(cptr);
1960 cptr->port = debuglevel;
1961 cptr->flags = 0;
1962 cptr->listener = cptr;
1963 /*
1964 * local[2] = cptr; winlocal
1965 */
1966 (void)strlcpy(cptr->sockhost, me.sockhost,
1967 sizeof cptr->sockhost);
1968 # ifndef _WIN32
1969 (void)printf("isatty = %d ttyname = %#x\n",
1970 isatty(2), (u_int)ttyname(2));
1971 if (!(bootopt & BOOT_TTY)) { /* leave debugging output on fd 2 */
1972 (void)truncate(LOGFILE, 0);
1973 if ((fd = open(LOGFILE, O_WRONLY | O_CREAT, 0600)) < 0)
1974 if ((fd = open("/dev/null", O_WRONLY)) < 0)
1975 exit(-1);
1976 if (fd != 2) {
1977 (void)dup2(fd, 2);
1978 (void)close(fd);
1979 }
1980 strncpyzt(cptr->name, LOGFILE, sizeof(cptr->name));
1981 } else if (isatty(2) && ttyname(2))
1982 strncpyzt(cptr->name, ttyname(2), sizeof(cptr->name));
1983 else
1984 # endif
1985 (void)strcpy(cptr->name, "FD2-Pipe");
1986 Debug((DEBUG_FATAL,
1987 "Debug: File <%s> Level: %d at %s", cptr->name,
1988 cptr->port, myctime(time(NULL))));
1989 } else
1990 /*
1991 * local[2] = NULL; winlocal
1992 */
1993 #endif
1994 return;
1995 }
1996
setup_signals()1997 static void setup_signals()
1998 {
1999 #ifndef _WIN32
2000 #ifdef POSIX_SIGNALS
2001 struct sigaction act;
2002 act.sa_handler = SIG_IGN;
2003 act.sa_flags = 0;
2004 (void)sigemptyset(&act.sa_mask);
2005 (void)sigaddset(&act.sa_mask, SIGPIPE);
2006 (void)sigaddset(&act.sa_mask, SIGALRM);
2007 # ifdef SIGWINCH
2008 (void)sigaddset(&act.sa_mask, SIGWINCH);
2009 (void)sigaction(SIGWINCH, &act, NULL);
2010 # endif
2011 (void)sigaction(SIGPIPE, &act, NULL);
2012 act.sa_handler = dummy;
2013 (void)sigaction(SIGALRM, &act, NULL);
2014 act.sa_handler = s_rehash;
2015 (void)sigemptyset(&act.sa_mask);
2016 (void)sigaddset(&act.sa_mask, SIGHUP);
2017 (void)sigaction(SIGHUP, &act, NULL);
2018 act.sa_handler = s_restart;
2019 (void)sigaddset(&act.sa_mask, SIGINT);
2020 (void)sigaction(SIGINT, &act, NULL);
2021 act.sa_handler = s_die;
2022 (void)sigaddset(&act.sa_mask, SIGTERM);
2023 (void)sigaction(SIGTERM, &act, NULL);
2024 #else
2025 # ifndef HAVE_RELIABLE_SIGNALS
2026 (void)signal(SIGPIPE, dummy);
2027 # ifdef SIGWINCH
2028 (void)signal(SIGWINCH, dummy);
2029 # endif
2030 # else
2031 # ifdef SIGWINCH
2032 (void)signal(SIGWINCH, SIG_IGN);
2033 # endif
2034 (void)signal(SIGPIPE, SIG_IGN);
2035 # endif
2036 (void)signal(SIGALRM, dummy);
2037 (void)signal(SIGHUP, s_rehash);
2038 (void)signal(SIGTERM, s_die);
2039 (void)signal(SIGINT, s_restart);
2040 #endif
2041 #ifdef RESTARTING_SYSTEMCALLS
2042 /*
2043 * ** At least on Apollo sr10.1 it seems continuing system calls
2044 * ** after signal is the default. The following 'siginterrupt'
2045 * ** should change that default to interrupting calls.
2046 */
2047 (void)siginterrupt(SIGALRM, 1);
2048 #endif
2049 #else
2050 (void)signal(SIGSEGV, CleanUpSegv);
2051 #endif
2052 }
2053