ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/src/ircd.c
Revision: 701
Committed: Sat Jun 24 19:24:39 2006 UTC (19 years, 2 months ago) by michael
Content type: text/x-csrc
File size: 16903 byte(s)
Log Message:
- Avoid header files including other header files
- Killed supported.h, fixed misc. compile errors

File Contents

# User Rev Content
1 adx 30 /*
2     * ircd-hybrid: an advanced Internet Relay Chat Daemon(ircd).
3     * ircd.c: Starts up and runs the ircd.
4     *
5     * Copyright (C) 2002 by the past and present ircd coders, and others.
6     *
7     * This program is free software; you can redistribute it and/or modify
8     * it under the terms of the GNU General Public License as published by
9     * the Free Software Foundation; either version 2 of the License, or
10     * (at your option) any later version.
11     *
12     * This program is distributed in the hope that it will be useful,
13     * but WITHOUT ANY WARRANTY; without even the implied warranty of
14     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15     * GNU General Public License for more details.
16     *
17     * You should have received a copy of the GNU General Public License
18     * along with this program; if not, write to the Free Software
19     * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
20     * USA
21     *
22 knight 31 * $Id$
23 adx 30 */
24    
25 adx 185 #ifdef IN_IRCD
26 adx 30 #include "stdinc.h"
27     #include "s_user.h"
28     #include "ircd.h"
29     #include "channel.h"
30     #include "channel_mode.h"
31     #include "client.h"
32     #include "common.h"
33     #include "hash.h"
34     #include "ircd_signal.h"
35     #include "motd.h"
36     #include "ircd_handler.h"
37     #include "msg.h" /* msgtab */
38     #include "hostmask.h"
39     #include "numeric.h"
40     #include "packet.h"
41     #include "parse.h"
42     #include "restart.h"
43     #include "s_auth.h"
44     #include "s_conf.h"
45 db 91 #include "parse_aline.h"
46     #include "s_serv.h"
47 adx 30 #include "send.h"
48     #include "whowas.h"
49 db 470 #include "conf/modules.h"
50 adx 30 #include "motd.h"
51 michael 217 #include "watch.h"
52 michael 684 #include "patchlevel.h"
53     #include "serno.h"
54 adx 30
55    
56     /* /quote set variables */
57     struct SetOptions GlobalSetOptions;
58 michael 515 struct ServerStatistics ServerStats;
59 adx 30 /* configuration set from ircd.conf */
60     struct config_file_entry ConfigFileEntry;
61     /* server info set from ircd.conf */
62     struct server_info ServerInfo;
63     /* admin info set from ircd.conf */
64     struct admin_info AdminInfo = { NULL, NULL, NULL };
65     struct Counter Count = { 0, 0, 0, 0, 0, 0, 0, 0 };
66     struct ServerState_t server_state = { 0 };
67     struct logging_entry ConfigLoggingEntry = { 1, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0} };
68     struct Client me; /* That's me */
69     struct LocalUser meLocalUser; /* That's also part of me */
70    
71     const char *logFileName = LPATH;
72     const char *pidFileName = PPATH;
73    
74     char **myargv;
75 michael 684 const char *ircd_version = PATCHLEVEL;
76     const char *serno = SERIALNUM;
77     char ircd_platform[IRCD_BUFSIZE];
78 adx 30
79     int dorehash = 0;
80     int doremotd = 0;
81    
82     /* Set to zero because it should be initialized later using
83     * initialize_server_capabs
84     */
85     int default_server_capabs = 0;
86    
87     #ifdef HAVE_LIBCRYPTO
88     int bio_spare_fd = -1;
89     #endif
90    
91     int splitmode;
92     int splitchecking;
93    
94 adx 68 static dlink_node *fdlimit_hook;
95    
96 adx 30 /* Do klines the same way hybrid-6 did them, i.e. at the
97     * top of the next io_loop instead of in the same loop as
98     * the klines are being applied.
99     *
100     * This should fix strange CPU starvation as very indirectly reported.
101     * (Why do you people not email bug reports? WHY? WHY?)
102     *
103     * - Dianora
104     */
105    
106     int rehashed_klines = 0;
107    
108     #ifndef _WIN32
109     /*
110     * print_startup - print startup information
111     */
112     static void
113     print_startup(int pid)
114     {
115     printf("ircd: version %s\n", ircd_version);
116     printf("ircd: pid %d\n", pid);
117     printf("ircd: running in %s mode from %s\n", !server_state.foreground ? "background"
118     : "foreground", ConfigFileEntry.dpath);
119     }
120    
121     static void
122     make_daemon(void)
123     {
124     int pid;
125    
126     if ((pid = fork()) < 0)
127     {
128     perror("fork");
129     exit(EXIT_FAILURE);
130     }
131     else if (pid > 0)
132     {
133     print_startup(pid);
134     exit(EXIT_SUCCESS);
135     }
136    
137     setsid();
138     }
139     #endif
140    
141     static int printVersion = 0;
142    
143 michael 695 static struct lgetopt myopts[] = {
144 adx 30 {"dlinefile", &ConfigFileEntry.dlinefile,
145     STRING, "File to use for dline.conf"},
146     {"configfile", &ConfigFileEntry.configfile,
147     STRING, "File to use for ircd.conf"},
148     {"klinefile", &ConfigFileEntry.klinefile,
149     STRING, "File to use for kline.conf"},
150     {"xlinefile", &ConfigFileEntry.xlinefile,
151     STRING, "File to use for xline.conf"},
152     {"logfile", &logFileName,
153     STRING, "File to use for ircd.log"},
154     {"pidfile", &pidFileName,
155     STRING, "File to use for process ID"},
156     {"foreground", &server_state.foreground,
157     YESNO, "Run in foreground (don't detach)"},
158     {"version", &printVersion,
159     YESNO, "Print version and exit"},
160     {"help", NULL, USAGE, "Print this text"},
161     {NULL, NULL, STRING, NULL},
162     };
163    
164     static void
165     io_loop(void)
166     {
167     while (1 == 1)
168     {
169     /*
170     * Maybe we want a flags word?
171     * ie. if (REHASHED_KLINES(global_flags))
172     * SET_REHASHED_KLINES(global_flags)
173     * CLEAR_REHASHED_KLINES(global_flags)
174     *
175     * - Dianora
176     */
177     if (rehashed_klines)
178     {
179     check_conf_klines();
180     rehashed_klines = 0;
181     }
182    
183     if (listing_client_list.head)
184     {
185     dlink_node *ptr = NULL, *ptr_next = NULL;
186     DLINK_FOREACH_SAFE(ptr, ptr_next, listing_client_list.head)
187     {
188     struct Client *client_p = ptr->data;
189     assert(client_p->localClient->list_task);
190 michael 398 safe_list_channels(client_p, client_p->localClient->list_task, 0);
191 adx 30 }
192     }
193    
194     /* Run pending events, then get the number of seconds to the next
195     * event
196     */
197     while (eventNextTime() <= CurrentTime)
198     eventRun();
199    
200     comm_select();
201     exit_aborted_clients();
202     free_exited_clients();
203     send_queued_all();
204    
205     /* Check to see whether we have to rehash the configuration .. */
206     if (dorehash)
207     {
208     rehash(1);
209     dorehash = 0;
210     }
211 michael 450
212 adx 30 if (doremotd)
213     {
214     read_message_file(&ConfigFileEntry.motd);
215     sendto_realops_flags(UMODE_ALL, L_ALL,
216     "Got signal SIGUSR1, reloading ircd motd file");
217     doremotd = 0;
218     }
219     }
220     }
221    
222     /* initalialize_global_set_options()
223     *
224     * inputs - none
225     * output - none
226     * side effects - This sets all global set options needed
227 adx 205 * XXX to be removed with old s_conf.c
228 adx 30 */
229     static void
230     initialize_global_set_options(void)
231     {
232     memset(&GlobalSetOptions, 0, sizeof(GlobalSetOptions));
233    
234     GlobalSetOptions.autoconn = 1;
235     GlobalSetOptions.spam_time = MIN_JOIN_LEAVE_TIME;
236     GlobalSetOptions.spam_num = MAX_JOIN_LEAVE_COUNT;
237    
238     if (ConfigFileEntry.default_floodcount)
239     GlobalSetOptions.floodcount = ConfigFileEntry.default_floodcount;
240     else
241     GlobalSetOptions.floodcount = 10;
242    
243     /* XXX I have no idea what to try here - Dianora */
244     GlobalSetOptions.joinfloodcount = 16;
245     GlobalSetOptions.joinfloodtime = 8;
246    
247 michael 644 GlobalSetOptions.split_servers = ConfigChannel.default_split_server_count;
248     GlobalSetOptions.split_users = ConfigChannel.default_split_user_count;
249 adx 30
250 michael 644 if (GlobalSetOptions.split_users &&
251     GlobalSetOptions.split_servers && (ConfigChannel.no_create_on_split ||
252     ConfigChannel.no_join_on_split))
253 adx 30 {
254     splitmode = 1;
255     splitchecking = 1;
256     }
257    
258     GlobalSetOptions.ident_timeout = IDENT_TIMEOUT;
259     GlobalSetOptions.idletime = ConfigFileEntry.idletime;
260 db 278 GlobalSetOptions.maxlisters = 10; /* XXX ya ya ya - db */
261 adx 30 }
262    
263     /* initialize_message_files()
264     *
265     * inputs - none
266     * output - none
267     * side effects - Set up all message files needed, motd etc.
268     */
269     static void
270     initialize_message_files(void)
271     {
272     init_message_file(USER_MOTD, MPATH, &ConfigFileEntry.motd);
273     init_message_file(OPER_MOTD, OPATH, &ConfigFileEntry.opermotd);
274     init_message_file(USER_LINKS, LIPATH, &ConfigFileEntry.linksfile);
275    
276     read_message_file(&ConfigFileEntry.motd);
277     read_message_file(&ConfigFileEntry.opermotd);
278     read_message_file(&ConfigFileEntry.linksfile);
279    
280     init_isupport();
281     }
282    
283     /* initialize_server_capabs()
284     *
285     * inputs - none
286     * output - none
287     */
288     static void
289     initialize_server_capabs(void)
290     {
291     add_capability("QS", CAP_QS, 1);
292     add_capability("EOB", CAP_EOB, 1);
293 adx 208 add_capability("HUB", CAP_HUB, 0);
294 adx 211 add_capability("TS6", CAP_TS6, 0);
295 adx 30 add_capability("ZIP", CAP_ZIP, 0);
296     add_capability("CLUSTER", CAP_CLUSTER, 1);
297     #ifdef HALFOPS
298     add_capability("HOPS", CAP_HOPS, 1);
299     #endif
300     }
301    
302     /* write_pidfile()
303     *
304     * inputs - filename+path of pid file
305     * output - NONE
306     * side effects - write the pid of the ircd to filename
307     */
308     static void
309     write_pidfile(const char *filename)
310     {
311     FBFILE *fb;
312    
313     if ((fb = fbopen(filename, "w")))
314     {
315     char buff[32];
316     unsigned int pid = (unsigned int)getpid();
317     size_t nbytes = ircsprintf(buff, "%u\n", pid);
318    
319     if ((fbputs(buff, fb, nbytes) == -1))
320     ilog(L_ERROR, "Error writing %u to pid file %s (%s)",
321     pid, filename, strerror(errno));
322    
323     fbclose(fb);
324     }
325     else
326     {
327     ilog(L_ERROR, "Error opening pid file %s", filename);
328     }
329     }
330    
331     /* check_pidfile()
332     *
333     * inputs - filename+path of pid file
334     * output - none
335     * side effects - reads pid from pidfile and checks if ircd is in process
336     * list. if it is, gracefully exits
337     * -kre
338     */
339     static void
340     check_pidfile(const char *filename)
341     {
342     #ifndef _WIN32
343     FBFILE *fb;
344     char buff[32];
345     pid_t pidfromfile;
346    
347     /* Don't do logging here, since we don't have log() initialised */
348     if ((fb = fbopen(filename, "r")))
349     {
350     if (fbgets(buff, 20, fb) == NULL)
351     {
352     /* log(L_ERROR, "Error reading from pid file %s (%s)", filename,
353     * strerror(errno));
354     */
355     }
356     else
357     {
358     pidfromfile = atoi(buff);
359    
360     if (!kill(pidfromfile, 0))
361     {
362     /* log(L_ERROR, "Server is already running"); */
363     printf("ircd: daemon is already running\n");
364     exit(-1);
365     }
366     }
367    
368     fbclose(fb);
369     }
370     else if (errno != ENOENT)
371     {
372     /* log(L_ERROR, "Error opening pid file %s", filename); */
373     }
374     #endif
375     }
376    
377     /* init_ssl()
378     *
379     * inputs - nothing
380     * output - nothing
381     * side effects - setups SSL context.
382     */
383     static void
384     init_ssl(void)
385     {
386     #ifdef HAVE_LIBCRYPTO
387 michael 452 SSL_library_init();
388 adx 30 SSL_load_error_strings();
389    
390     ServerInfo.ctx = SSL_CTX_new(SSLv23_server_method());
391 michael 450
392 adx 30 if (!ServerInfo.ctx)
393     {
394     const char *s;
395    
396     fprintf(stderr, "ERROR: Could not initialize the SSL context -- %s\n",
397     s = ERR_lib_error_string(ERR_get_error()));
398     ilog(L_CRIT, "ERROR: Could not initialize the SSL context -- %s\n", s);
399     }
400    
401     SSL_CTX_set_options(ServerInfo.ctx, SSL_OP_NO_SSLv2);
402     SSL_CTX_set_options(ServerInfo.ctx, SSL_OP_TLS_ROLLBACK_BUG|SSL_OP_ALL);
403     SSL_CTX_set_verify(ServerInfo.ctx, SSL_VERIFY_NONE, NULL);
404    
405     bio_spare_fd = save_spare_fd("SSL private key validation");
406     #endif /* HAVE_LIBCRYPTO */
407     }
408    
409     /* init_callbacks()
410     *
411     * inputs - nothing
412     * output - nothing
413     * side effects - setups standard hook points
414     */
415     static void
416     init_callbacks(void)
417     {
418 adx 211 entering_umode_cb = register_callback("entering_umode", NULL);
419 adx 178 iorecv_cb = register_callback("iorecv", iorecv_default);
420     iosend_cb = register_callback("iosend", iosend_default);
421 adx 30 iorecvctrl_cb = register_callback("iorecvctrl", NULL);
422     iosendctrl_cb = register_callback("iosendctrl", NULL);
423 adx 211 uid_get_cb = register_callback("uid_get", uid_get);
424     umode_cb = register_callback("changing_umode", change_simple_umode);
425 adx 30 }
426    
427 adx 68 static void *
428     changing_fdlimit(va_list args)
429     {
430     int old_fdlimit = hard_fdlimit;
431     int fdmax = va_arg(args, int);
432    
433 michael 649 /*
434     * allow MAXCLIENTS_MIN clients even at the cost of MAX_BUFFER and
435     * some not really LEAKED_FDS
436     */
437     fdmax = LIBIO_MAX(fdmax, LEAKED_FDS + MAX_BUFFER + MAXCLIENTS_MIN);
438 adx 68
439     pass_callback(fdlimit_hook, fdmax);
440    
441     if (ServerInfo.max_clients > MAXCLIENTS_MAX)
442     {
443     if (old_fdlimit != 0)
444     sendto_realops_flags(UMODE_ALL, L_ALL,
445     "HARD_FDLIMIT changed to %d, adjusting MAXCLIENTS to %d",
446     hard_fdlimit, MAXCLIENTS_MAX);
447    
448     ServerInfo.max_clients = MAXCLIENTS_MAX;
449     }
450    
451     return NULL;
452     }
453    
454 adx 185 EXTERN int
455 adx 30 main(int argc, char *argv[])
456     {
457 michael 515 /*
458     * Check to see if the user is running us as root, which is a nono
459 adx 30 */
460     #ifndef _WIN32
461     if (geteuid() == 0)
462     {
463     fprintf(stderr, "Don't run ircd as root!!!\n");
464 adx 62 return 1;
465 adx 30 }
466    
467     /* Setup corefile size immediately after boot -kre */
468     setup_corefile();
469     #endif
470    
471     memset(&ServerInfo, 0, sizeof(ServerInfo));
472 michael 515 memset(&ServerStats, 0, sizeof(ServerStats));
473 adx 30
474     ConfigFileEntry.dpath = DPATH;
475     ConfigFileEntry.configfile = CPATH; /* Server configuration file */
476     ConfigFileEntry.klinefile = KPATH; /* Server kline file */
477     ConfigFileEntry.xlinefile = XPATH; /* Server xline file */
478     ConfigFileEntry.rxlinefile = RXPATH; /* Server regex xline file */
479     ConfigFileEntry.rklinefile = RKPATH; /* Server regex kline file */
480     ConfigFileEntry.dlinefile = DLPATH; /* dline file */
481     ConfigFileEntry.glinefile = GPATH; /* gline log file */
482     ConfigFileEntry.cresvfile = CRESVPATH; /* channel resv file */
483     ConfigFileEntry.nresvfile = NRESVPATH; /* nick resv file */
484     myargv = argv;
485     umask(077); /* better safe than sorry --SRB */
486    
487     parseargs(&argc, &argv, myopts);
488    
489     if (printVersion)
490     {
491     printf("ircd: version %s\n", ircd_version);
492     exit(EXIT_SUCCESS);
493     }
494    
495     if (chdir(ConfigFileEntry.dpath))
496     {
497     perror("chdir");
498     exit(EXIT_FAILURE);
499     }
500    
501     init_ssl();
502    
503     #ifndef _WIN32
504     if (!server_state.foreground)
505     make_daemon();
506     else
507     print_startup(getpid());
508 adx 77 #endif
509 adx 30
510 adx 87 libio_init(!server_state.foreground);
511 adx 229 outofmemory = ircd_outofmemory;
512     fdlimit_hook = install_hook(fdlimit_cb, changing_fdlimit);
513    
514 adx 230 check_pidfile(pidFileName);
515 adx 229 setup_signals();
516 michael 684 libio_get_platform(ircd_platform, sizeof(ircd_platform));
517 adx 229 init_log(logFileName);
518     ServerInfo.can_use_v6 = check_can_use_v6();
519    
520 db 228 /* make_dlink_node() cannot be called until after libio_init() */
521     memset(&me, 0, sizeof(me));
522     memset(&meLocalUser, 0, sizeof(meLocalUser));
523 michael 515
524 db 228 me.localClient = &meLocalUser;
525     me.from = me.servptr = &me;
526     me.lasttime = me.since = me.firsttime = CurrentTime;
527    
528     SetMe(&me);
529     make_server(&me);
530     dlinkAdd(&me, &me.node, &global_client_list);
531     dlinkAdd(&me, make_dlink_node(), &global_serv_list);
532    
533 adx 30 init_callbacks();
534     initialize_message_files();
535     init_hash();
536     init_ip_hash_table(); /* client host ip hash table */
537     init_host_hash(); /* Host-hashtable. */
538     clear_tree_parse();
539     init_client();
540     init_class();
541 michael 655 whowas_init();
542     watch_init();
543    
544 adx 30 init_auth(); /* Initialise the auth code */
545 michael 695 channel_init();
546 adx 48 init_channel_modes();
547 adx 211 initialize_server_capabs(); /* Set up default_server_capabs */
548 michael 504
549 adx 211 read_conf_files(1); /* cold start init conf files */
550     check_class();
551    
552 adx 30 if (ServerInfo.name == NULL)
553     {
554 michael 515 ilog(L_CRIT, "ERROR: No server name specified in serverinfo block.");
555 adx 30 exit(EXIT_FAILURE);
556     }
557 michael 450
558 adx 30 strlcpy(me.name, ServerInfo.name, sizeof(me.name));
559    
560     /* serverinfo{} description must exist. If not, error out.*/
561     if (ServerInfo.description == NULL)
562     {
563     ilog(L_CRIT,
564     "ERROR: No server description specified in serverinfo block.");
565     exit(EXIT_FAILURE);
566     }
567 michael 450
568 adx 30 strlcpy(me.info, ServerInfo.description, sizeof(me.info));
569    
570     hash_add_client(&me);
571    
572 adx 211 init_uid(); /* XXX move this one up after inculcating new conf system */
573     initialize_global_set_options(); /* and this one is going to be deleted */
574 michael 257
575 adx 30 #ifndef STATIC_MODULES
576     if (chdir(MODPATH))
577     {
578     ilog (L_CRIT, "Could not load core modules. Terminating!");
579     exit(EXIT_FAILURE);
580     }
581 michael 257
582 adx 475 boot_modules(1);
583 michael 257
584 adx 30 /* Go back to DPATH after checking to see if we can chdir to MODPATH */
585     chdir(ConfigFileEntry.dpath);
586     #else
587     load_all_modules(1);
588     #endif
589     /*
590     * assemble_umode_buffer() has to be called after
591     * reading conf/loading modules.
592     */
593     assemble_umode_buffer();
594    
595     write_pidfile(pidFileName);
596    
597     ilog(L_NOTICE, "Server Ready");
598    
599     eventAddIsh("cleanup_tklines", cleanup_tklines, NULL, CLEANUP_TKLINES_TIME);
600    
601     /* We want try_connections to be called as soon as possible now! -- adrian */
602     /* No, 'cause after a restart it would cause all sorts of nick collides */
603     eventAddIsh("try_connections", try_connections, NULL, STARTUP_CONNECTIONS_TIME);
604    
605     eventAddIsh("collect_zipstats", collect_zipstats, NULL, ZIPSTATS_TIME);
606    
607     /* Setup the timeout check. I'll shift it later :) -- adrian */
608     eventAddIsh("comm_checktimeouts", comm_checktimeouts, NULL, 1);
609    
610 adx 205 /* XXX to be removed with old s_conf.c [superseded] */
611 adx 30 if (ConfigServerHide.links_delay > 0)
612     eventAddIsh("write_links_file", write_links_file, NULL, ConfigServerHide.links_delay);
613     else
614     ConfigServerHide.links_disabled = 1;
615    
616 adx 205 if (splitmode) /* XXX */
617 adx 30 eventAddIsh("check_splitmode", check_splitmode, NULL, 60);
618    
619     io_loop();
620 michael 450 return 0;
621 adx 30 }
622 adx 185
623     #else
624    
625     #include <windows.h>
626    
627     extern __declspec(dllimport) main(int, char **);
628    
629     /*
630     * Initial entry point for Win32 GUI applications, called by the C runtime.
631     *
632     * It should be only a wrapper for main(), since when compiled as a console
633     * application, main() is called instead.
634     */
635     int WINAPI
636     WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
637     LPSTR lpCmdLine, int nCmdShow)
638     {
639     /* Do we really need these pidfile, logfile etc arguments?
640     * And we are not on a console, so -help or -foreground is meaningless. */
641    
642     char *argv[2] = {"ircd", NULL};
643    
644     return main(1, argv);
645     }
646    
647     #endif

Properties

Name Value
svn:eol-style native
svn:keywords Id Revision