ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/src/ircd.c
Revision: 153
Committed: Mon Oct 17 21:20:34 2005 UTC (20 years, 9 months ago) by adx
Content type: text/x-csrc
File size: 18398 byte(s)
Log Message:
- compile libio as a dll on win32
- next step is compiling the whole ircd as a dll to export its symbols
- after that, we'll be able to support loadable *.dll modules.

NOTE: m_operspy.c doesn't compile now (error at localClient->iline)

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

Properties

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