ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/src/ircd.c
Revision: 8899
Committed: Sun Apr 21 18:08:14 2019 UTC (6 years, 4 months ago) by michael
Content type: text/x-csrc
File size: 13310 byte(s)
Log Message:
- Replace gettimeofday() with clock_gettime(). We're not falling back to gettimeofday() for old/weird systems that don't have clock_gettime()

File Contents

# User Rev Content
1 adx 30 /*
2 michael 2916 * ircd-hybrid: an advanced, lightweight Internet Relay Chat Daemon (ircd)
3 adx 30 *
4 michael 8752 * Copyright (c) 1997-2019 ircd-hybrid development team
5 adx 30 *
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 2 of the License, or
9     * (at your option) 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 michael 4565 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
19 adx 30 * USA
20     */
21    
22 michael 2916 /*! \file ircd.c
23     * \brief Starts up and runs the ircd.
24     * \version $Id$
25     */
26    
27 adx 30 #include "stdinc.h"
28 michael 3347 #include "user.h"
29 michael 1011 #include "list.h"
30 adx 30 #include "ircd.h"
31     #include "channel.h"
32 michael 8089 #include "channel_mode.h"
33 adx 30 #include "client.h"
34     #include "event.h"
35     #include "fdlist.h"
36     #include "hash.h"
37 michael 6161 #include "id.h"
38 adx 30 #include "irc_string.h"
39     #include "ircd_signal.h"
40     #include "motd.h"
41 michael 1632 #include "conf.h"
42 adx 30 #include "hostmask.h"
43     #include "parse.h"
44 michael 3322 #include "res.h"
45 adx 30 #include "restart.h"
46 michael 982 #include "rng_mt.h"
47 adx 30 #include "s_bsd.h"
48 michael 1309 #include "log.h"
49 michael 6481 #include "server.h"
50 michael 8166 #include "server_capab.h"
51 adx 30 #include "send.h"
52     #include "modules.h"
53     #include "memory.h"
54     #include "ircd_getopt.h"
55 michael 1622 #include "conf_db.h"
56 michael 1632 #include "conf_class.h"
57 michael 4325 #include "ipcache.h"
58 michael 6185 #include "isupport.h"
59 michael 8729 #include "patchlevel.h"
60     #include "serno.h"
61 adx 30
62 michael 1858
63 michael 5737 struct SetOptions GlobalSetOptions; /* /quote set variables */
64 michael 5602 struct Counter Count;
65     struct ServerState_t server_state;
66     struct ServerStatistics ServerStats;
67 michael 7330 struct ServerTime SystemTime;
68 michael 5737 struct Connection meConnection; /* That's also part of me */
69 michael 5470 struct Client me = { .connection = &meConnection }; /* That's me */
70 adx 30
71 michael 5460 char **myargv;
72 adx 30 const char *logFileName = LPATH;
73     const char *pidFileName = PPATH;
74    
75 michael 8658 bool dorehash;
76     bool doremotd;
77 adx 30
78 michael 8658 static bool printVersion;
79 michael 6735
80     static struct lgetopt myopts[] =
81     {
82     { "configfile", &ConfigGeneral.configfile,
83     STRING, "File to use for ircd.conf" },
84     { "klinefile", &ConfigGeneral.klinefile,
85     STRING, "File to use for kline database" },
86     { "dlinefile", &ConfigGeneral.dlinefile,
87     STRING, "File to use for dline database" },
88     { "xlinefile", &ConfigGeneral.xlinefile,
89     STRING, "File to use for xline database" },
90     { "resvfile", &ConfigGeneral.resvfile,
91     STRING, "File to use for resv database" },
92     { "logfile", &logFileName,
93     STRING, "File to use for ircd.log" },
94     { "pidfile", &pidFileName,
95     STRING, "File to use for process ID" },
96     { "foreground", &server_state.foreground,
97 michael 8862 BOOLEAN, "Run in foreground (don't detach)" },
98 michael 6735 { "version", &printVersion,
99 michael 8862 BOOLEAN, "Print version and exit" },
100 michael 6735 { "help", NULL, USAGE, "Print this text" },
101     { NULL, NULL, STRING, NULL },
102     };
103    
104 michael 4094 static struct event event_cleanup_tklines =
105     {
106     .name = "cleanup_tklines",
107     .handler = cleanup_tklines,
108     .when = CLEANUP_TKLINES_TIME
109     };
110    
111     static struct event event_try_connections =
112     {
113     .name = "try_connections",
114     .handler = try_connections,
115     .when = STARTUP_CONNECTIONS_TIME
116     };
117    
118     static struct event event_comm_checktimeouts =
119     {
120     .name = "comm_checktimeouts",
121     .handler = comm_checktimeouts,
122     .when = 1
123     };
124    
125     static struct event event_save_all_databases =
126     {
127     .name = "save_all_databases",
128     .handler = save_all_databases,
129     .when = DATABASE_UPDATE_TIMEOUT
130     };
131    
132     struct event event_write_links_file =
133     {
134     .name = "write_links_file",
135     .handler = write_links_file,
136     };
137    
138    
139 adx 30 void
140     set_time(void)
141     {
142 michael 8899 struct timespec newtime = { .tv_sec = 0, .tv_nsec = 0 };
143 adx 30
144 michael 8899 if (clock_gettime(CLOCK_REALTIME, &newtime) == -1)
145 adx 30 {
146 michael 6482 char buf[IRCD_BUFSIZE];
147    
148     snprintf(buf, sizeof(buf), "Clock failure, TS can be corrupted: %s",
149     strerror(errno));
150 michael 8706 server_die(buf, false);
151 adx 30 }
152    
153 michael 7330 if ((uintmax_t)newtime.tv_sec < CurrentTime)
154 adx 30 {
155 michael 6782 ilog(LOG_TYPE_IRCD, "System clock is running backwards - (%ju < %ju)",
156 michael 7330 (uintmax_t)newtime.tv_sec, CurrentTime);
157 michael 2980 sendto_realops_flags(UMODE_DEBUG, L_ALL, SEND_NOTICE,
158 michael 6782 "System clock is running backwards - (%ju < %ju)",
159 michael 7330 (uintmax_t)newtime.tv_sec, CurrentTime);
160     event_set_back_events(CurrentTime - (uintmax_t)newtime.tv_sec);
161 adx 30 }
162    
163 michael 6481 SystemTime.tv_sec = newtime.tv_sec;
164 michael 8899 SystemTime.tv_nsec = newtime.tv_nsec;
165 adx 30 }
166    
167     static void
168     io_loop(void)
169     {
170 michael 8664 while (true)
171 adx 30 {
172     if (listing_client_list.head)
173     {
174 michael 4815 dlink_node *node = NULL, *node_next = NULL;
175     DLINK_FOREACH_SAFE(node, node_next, listing_client_list.head)
176 michael 8656 safe_list_channels(node->data, false);
177 adx 30 }
178    
179 michael 4094 /* Run pending events */
180     event_run();
181 adx 30
182     comm_select();
183     exit_aborted_clients();
184     free_exited_clients();
185    
186 michael 6735 /* Check to see whether we have to rehash the configuration. */
187 michael 8658 if (dorehash == true)
188 adx 30 {
189 michael 8658 conf_rehash(true);
190     dorehash = false;
191 adx 30 }
192 michael 3215
193 michael 8658 if (doremotd == true)
194 adx 30 {
195 michael 2150 motd_recache();
196 michael 6318 sendto_realops_flags(UMODE_SERVNOTICE, L_ALL, SEND_NOTICE,
197 michael 3065 "Got signal SIGUSR1, reloading motd file(s)");
198 michael 8658 doremotd = false;
199 adx 30 }
200     }
201     }
202    
203     /* initalialize_global_set_options()
204     *
205     * inputs - none
206     * output - none
207 michael 2916 * side effects - This sets all global set options needed
208 adx 30 */
209     static void
210     initialize_global_set_options(void)
211     {
212 michael 5489 GlobalSetOptions.maxclients = ConfigServerInfo.default_max_clients;
213 michael 8800 GlobalSetOptions.autoconn = true;
214 adx 30 GlobalSetOptions.spam_time = MIN_JOIN_LEAVE_TIME;
215 michael 5499 GlobalSetOptions.spam_num = MAX_JOIN_LEAVE_COUNT;
216     GlobalSetOptions.floodcount = ConfigGeneral.default_floodcount;
217 michael 7858 GlobalSetOptions.floodtime = ConfigGeneral.default_floodtime;
218 michael 5489 GlobalSetOptions.joinfloodcount = ConfigChannel.default_join_flood_count;
219     GlobalSetOptions.joinfloodtime = ConfigChannel.default_join_flood_time;
220 adx 30 }
221    
222     /* write_pidfile()
223     *
224     * inputs - filename+path of pid file
225     * output - NONE
226     * side effects - write the pid of the ircd to filename
227     */
228     static void
229     write_pidfile(const char *filename)
230     {
231 michael 1325 FILE *fb;
232 adx 30
233 michael 1325 if ((fb = fopen(filename, "w")))
234 adx 30 {
235 michael 6470 char buf[IRCD_BUFSIZE];
236 adx 30 unsigned int pid = (unsigned int)getpid();
237    
238 michael 6470 snprintf(buf, sizeof(buf), "%u\n", pid);
239 michael 1325
240 michael 6470 if (fputs(buf, fb) == -1)
241 michael 5737 ilog(LOG_TYPE_IRCD, "Error writing to pid file %s: %s",
242     filename, strerror(errno));
243 adx 30
244 michael 1325 fclose(fb);
245 adx 30 }
246     else
247 michael 5566 ilog(LOG_TYPE_IRCD, "Error opening pid file %s: %s",
248 michael 4748 filename, strerror(errno));
249 adx 30 }
250    
251     /* check_pidfile()
252     *
253     * inputs - filename+path of pid file
254     * output - none
255     * side effects - reads pid from pidfile and checks if ircd is in process
256     * list. if it is, gracefully exits
257     * -kre
258     */
259     static void
260     check_pidfile(const char *filename)
261     {
262 michael 1325 FILE *fb;
263 michael 6470 char buf[IRCD_BUFSIZE];
264 adx 30
265 michael 1325 if ((fb = fopen(filename, "r")))
266 adx 30 {
267 michael 8702 if (fgets(buf, 20, fb) == NULL)
268 michael 6260 ilog(LOG_TYPE_IRCD, "Error reading from pid file %s: %s",
269     filename, strerror(errno));
270 adx 30 else
271     {
272 michael 6481 pid_t pid = atoi(buf);
273 adx 30
274 michael 8702 if (kill(pid, 0) == 0)
275 adx 30 {
276     /* log(L_ERROR, "Server is already running"); */
277     printf("ircd: daemon is already running\n");
278 michael 6646 exit(EXIT_FAILURE);
279 adx 30 }
280     }
281    
282 michael 1325 fclose(fb);
283 adx 30 }
284     else if (errno != ENOENT)
285 michael 6260 ilog(LOG_TYPE_IRCD, "Error opening pid file %s: %s",
286     filename, strerror(errno));
287 adx 30 }
288    
289     /* setup_corefile()
290     *
291     * inputs - nothing
292     * output - nothing
293     * side effects - setups corefile to system limits.
294     * -kre
295     */
296     static void
297     setup_corefile(void)
298     {
299     struct rlimit rlim; /* resource limits */
300    
301     /* Set corefilesize to maximum */
302 michael 8702 if (getrlimit(RLIMIT_CORE, &rlim) == 0)
303 adx 30 {
304     rlim.rlim_cur = rlim.rlim_max;
305     setrlimit(RLIMIT_CORE, &rlim);
306     }
307     }
308    
309 michael 8774 static void
310     setup_fdlimit(void)
311     {
312     struct rlimit rlim; /* resource limits */
313    
314     if (getrlimit(RLIMIT_NOFILE, &rlim))
315     {
316     fprintf(stderr, "getrlimit: couldn't get maximum number of file descriptors: %s\n",
317     strerror(errno));
318     exit(EXIT_FAILURE);
319     }
320    
321     if (rlim.rlim_max > 0xFFFF)
322     rlim.rlim_max = 0xFFFF;
323     rlim.rlim_cur = rlim.rlim_max;
324    
325     if (setrlimit(RLIMIT_NOFILE, &rlim) == 0)
326     hard_fdlimit = rlim.rlim_cur;
327     else
328     {
329     fprintf(stderr, "setrlimit: couldn't set maximum number of file descriptors: %s\n",
330     strerror(errno));
331     exit(EXIT_FAILURE);
332     }
333     }
334    
335 michael 6735 /*
336     * print_startup - print startup information
337     */
338     static void
339     print_startup(int pid)
340     {
341 michael 8729 printf("ircd: version %s(%s)\n", PATCHLEVEL, SERIALNUM);
342 michael 6735 printf("ircd: pid %d\n", pid);
343     printf("ircd: running in %s mode from %s\n", !server_state.foreground ? "background"
344     : "foreground", ConfigGeneral.dpath);
345     }
346    
347     static void
348     make_daemon(void)
349     {
350     int pid;
351    
352     if ((pid = fork()) < 0)
353     {
354     perror("fork");
355     exit(EXIT_FAILURE);
356     }
357     else if (pid > 0)
358     {
359     print_startup(pid);
360     exit(EXIT_SUCCESS);
361     }
362    
363     setsid();
364     }
365    
366 adx 30 int
367     main(int argc, char *argv[])
368     {
369 michael 2253 /* Check to see if the user is running us as root, which is a nono */
370 michael 8702 if (geteuid() == 0)
371 adx 30 {
372 michael 3525 fprintf(stderr, "ERROR: This server won't run as root/superuser\n");
373 michael 982 return -1;
374 adx 30 }
375    
376     /* Setup corefile size immediately after boot -kre */
377     setup_corefile();
378    
379 michael 8774 setup_fdlimit();
380    
381 michael 5545 /* Save server boot time right away, so getrusage works correctly */
382 adx 30 set_time();
383    
384 michael 5545 /* It's not random, but it ought to be a little harder to guess */
385 michael 8899 init_genrand(SystemTime.tv_sec ^ (SystemTime.tv_nsec / 1000 | (getpid() << 20)));
386 michael 982
387 michael 4340 ConfigGeneral.dpath = DPATH;
388     ConfigGeneral.spath = SPATH;
389     ConfigGeneral.mpath = MPATH;
390     ConfigGeneral.configfile = CPATH; /* Server configuration file */
391     ConfigGeneral.klinefile = KPATH; /* Server kline file */
392     ConfigGeneral.xlinefile = XPATH; /* Server xline file */
393     ConfigGeneral.dlinefile = DLPATH; /* dline file */
394     ConfigGeneral.resvfile = RESVPATH; /* resv file */
395 michael 1702
396 adx 30 myargv = argv;
397 michael 5723 umask(077); /* umask 077: u=rwx,g=,o= */
398 adx 30
399     parseargs(&argc, &argv, myopts);
400    
401 michael 8660 if (printVersion == true)
402 adx 30 {
403 michael 8729 printf("ircd: version %s(%s)\n", PATCHLEVEL, SERIALNUM);
404 adx 30 exit(EXIT_SUCCESS);
405     }
406    
407 michael 4340 if (chdir(ConfigGeneral.dpath))
408 adx 30 {
409     perror("chdir");
410     exit(EXIT_FAILURE);
411     }
412    
413 michael 8660 if (server_state.foreground == false)
414 adx 30 {
415     make_daemon();
416 michael 8414 close_standard_fds(); /* this needs to be before comm_select_init()! */
417 adx 30 }
418     else
419     print_startup(getpid());
420    
421     setup_signals();
422    
423     /* We need this to initialise the fd array before anything else */
424     fdlist_init();
425 michael 1831 log_set_file(LOG_TYPE_IRCD, 0, logFileName);
426 michael 4415
427 michael 8414 comm_select_init(); /* This needs to be setup early ! -- adrian */
428 michael 7279 tls_init();
429 michael 2253
430 adx 30 /* Check if there is pidfile and daemon already running */
431     check_pidfile(pidFileName);
432    
433 michael 6185 isupport_init();
434 michael 1798 hash_init();
435 michael 4319 ipcache_init();
436 michael 1798 client_init();
437 michael 1632 class_init();
438 michael 7569 resolver_init(); /* Needs to be setup before the io loop */
439 michael 1404 modules_init();
440 michael 8656 read_conf_files(true); /* cold start init conf files */
441 michael 8166 capab_init(); /* Set up default_server_capabs */
442 michael 5489 initialize_global_set_options(); /* Has to be called after read_conf_files() */
443 michael 8089 channel_mode_init();
444 michael 2216 read_links_file();
445 michael 2150 motd_init();
446 michael 6189 user_modes_init();
447 adx 30
448 michael 4340 if (EmptyString(ConfigServerInfo.name))
449 michael 1115 {
450 michael 1247 ilog(LOG_TYPE_IRCD, "ERROR: No server name specified in serverinfo block.");
451 michael 1115 exit(EXIT_FAILURE);
452     }
453    
454 michael 4340 strlcpy(me.name, ConfigServerInfo.name, sizeof(me.name));
455 adx 30
456 michael 6481 /* serverinfo {} description must exist. If not, error out.*/
457 michael 4340 if (EmptyString(ConfigServerInfo.description))
458 adx 30 {
459 michael 1247 ilog(LOG_TYPE_IRCD, "ERROR: No server description specified in serverinfo block.");
460 adx 30 exit(EXIT_FAILURE);
461     }
462 michael 885
463 michael 4340 strlcpy(me.info, ConfigServerInfo.description, sizeof(me.info));
464 adx 30
465 michael 6156 if (EmptyString(ConfigServerInfo.sid))
466     {
467     ilog(LOG_TYPE_IRCD, "Generating server ID");
468     generate_sid();
469     }
470     else
471     strlcpy(me.id, ConfigServerInfo.sid, sizeof(me.id));
472    
473 michael 6464 init_uid();
474    
475 michael 5545 me.from = &me;
476     me.servptr = &me;
477     me.connection->lasttime = CurrentTime;
478     me.connection->since = CurrentTime;
479 michael 4588 me.connection->firsttime = CurrentTime;
480 adx 30
481     SetMe(&me);
482 michael 8426 server_make(&me);
483 adx 30
484 michael 1115 hash_add_id(&me);
485 adx 30 hash_add_client(&me);
486 michael 2916
487 michael 7963 dlinkAdd(&me, &me.node, &global_server_list);
488 adx 30
489 michael 6928 load_kline_database(ConfigGeneral.klinefile);
490     load_dline_database(ConfigGeneral.dlinefile);
491     load_xline_database(ConfigGeneral.xlinefile);
492     load_resv_database(ConfigGeneral.resvfile);
493 michael 1622
494 michael 8660 load_all_modules(true);
495 adx 30 load_conf_modules();
496 michael 8660 load_core_modules(true);
497 michael 1115
498 adx 30 write_pidfile(pidFileName);
499    
500 michael 4094 event_addish(&event_cleanup_tklines, NULL);
501 adx 30
502     /* We want try_connections to be called as soon as possible now! -- adrian */
503     /* No, 'cause after a restart it would cause all sorts of nick collides */
504 michael 4094 event_addish(&event_try_connections, NULL);
505 adx 30
506     /* Setup the timeout check. I'll shift it later :) -- adrian */
507 michael 4399 event_add(&event_comm_checktimeouts, NULL);
508 adx 30
509 michael 4094 event_addish(&event_save_all_databases, NULL);
510 michael 1625
511 michael 8660 if (ConfigServerHide.flatten_links_delay && event_write_links_file.active == false)
512 michael 4094 {
513 michael 6597 event_write_links_file.when = ConfigServerHide.flatten_links_delay;
514 michael 6636 event_add(&event_write_links_file, NULL);
515 michael 4094 }
516 adx 30
517 michael 8729 ilog(LOG_TYPE_IRCD, "Server ready. Running version: %s(%s)", PATCHLEVEL, SERIALNUM);
518 adx 30 io_loop();
519 michael 6464
520 michael 885 return 0;
521 adx 30 }

Properties

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