5 Author: Pekka Riikonen <priikone@silcnet.org>
7 Copyright (C) 1997 - 2005 Pekka Riikonen
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; version 2 of the License.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
20 * Created: Wed Mar 19 00:17:12 1997
22 * This is the main program for the SILC daemon. This parses command
23 * line arguments and creates the server object.
27 #include "serverincludes.h"
28 #include "server_internal.h"
29 #include "silcversion.h"
31 /* For now, we'll have this one server context global for this module. */
32 static SilcServer silcd;
34 static void silc_usage(void);
36 #ifdef HAVE_GETOPT_LONG
37 /* Long command line options */
38 static struct option long_opts[] =
40 { "config-file", 1, NULL, 'f' },
41 { "passphrase", 1, NULL, 'p' },
42 { "debug", 2, NULL, 'd' },
43 { "debug-level", 1, NULL, 'D' },
44 { "hexdump", 0, NULL, 'x' },
45 { "help", 0, NULL, 'h' },
46 { "foreground", 0, NULL, 'F' },
47 { "version", 0, NULL,'V' },
49 /* Key management options */
50 { "create-key-pair", 1, NULL, 'C' },
51 { "pkcs", 1, NULL, 10 },
52 { "bits", 1, NULL, 11 },
53 { "identifier", 1, NULL, 12 },
57 #endif /* HAVE_GETOPT_LONG */
59 /* Command line option variables */
60 static char *opt_keypath = NULL;
61 static char *opt_pkcs = "rsa";
62 static char *opt_identifier = NULL;
63 static int opt_bits = 2048;
65 /* Prints out the usage of silc client */
67 static void silc_usage(void)
70 "Usage: silcd [options]\n"
73 " -f --config-file=FILE Alternate configuration file\n"
74 " -d --debug=string Enable debugging (Implies --foreground)\n"
75 " -D --debug-level=level Enable debugging (Implies --foreground)\n"
76 " -x --hexdump Enable hexdumps (Implies --debug)\n"
77 " -h --help Display this message\n"
78 " -F --foreground Dont fork\n"
79 " -V --version Display version\n"
81 " Key Management Options:\n"
82 " -C, --create-key-pair=PATH Create new public key pair\n"
83 " --pkcs=PKCS Set the PKCS of the public key pair\n"
84 " --bits=VALUE Set length of the public key pair\n"
85 " --identifier=IDENTIFIER Public key identifier\n"
87 " The public key identifier may be of the following format:\n"
89 " UN=<username>, HN=<hostname or IP>, RN=<real name>, E=<email>,\n"
90 " O=<organization>, C=<country>\n"
92 " The UN and HN must be provided, the others are optional. If the\n"
93 " --identifier option is not used an identifier will be created for\n"
94 " the public key automatically.\n"
96 " Example identifier: \"UN=foobar, HN=foo.bar.com, RN=Foo T. Bar, \n"
97 " E=foo@bar.com, C=FI\"\n"
102 /* Die if a *valid* pid file exists already */
104 static void silc_server_checkpid(SilcServer silcd)
106 if (silcd->config->server_info->pid_file) {
111 SILC_LOG_DEBUG(("Checking for another silcd running"));
112 buf = silc_file_readfile(silcd->config->server_info->pid_file, &buf_len);
119 kill(oldpid, SIGCHLD); /* this signal does nothing, check if alive */
120 if (errno != ESRCH) {
121 fprintf(stderr, "\nI detected another daemon running with the "
123 fprintf(stderr, "Please change the config file, or erase the %s\n",
124 silcd->config->server_info->pid_file);
130 /* Drop root privileges. If some system call fails, die. */
132 static void silc_server_drop_privs(SilcServer server)
134 /* Are we executing silcd as root or a regular user? */
136 SILC_LOG_DEBUG(("Server started as user"));
143 SILC_LOG_DEBUG(("Server started as root. Dropping privileges."));
145 /* Get the values given for user and group in configuration file */
146 user = server->config->server_info->user;
147 group = server->config->server_info->group;
149 if (!user || !group) {
150 fprintf(stderr, "Error:"
151 "\tSILC server must not be run as root. For the security of your\n"
152 "\tsystem it is strongly suggested that you run SILC under dedicated\n"
153 "\tuser account. Modify the ServerInfo configuration section to run\n"
154 "\tthe server as non-root user.\n");
158 /* Check whether the user/group does not begin with a number */
159 if (isdigit(user[0]) || isdigit(group[0])) {
160 SILC_LOG_DEBUG(("User and/or group starts with a number"));
161 fprintf(stderr, "Invalid user and/or group information\n");
162 fprintf(stderr, "Please assign them as names, not numbers\n");
166 if (!(pw = getpwnam(user))) {
167 fprintf(stderr, "Error: No such user %s found.\n", user);
170 if (!(gr = getgrnam(group))) {
171 fprintf(stderr, "Error: No such group %s found.\n", group);
175 /* Check whether user and/or group is set to root. If yes, exit
176 immediately. Otherwise, setgid and setuid server to user.group */
177 if ((gr->gr_gid == 0) || (pw->pw_uid == 0)) {
178 fprintf(stderr, "Error:"
179 "\tSILC server must not be run as root. For the security of your\n"
180 "\tsystem it is strongly suggested that you run SILC under dedicated\n"
181 "\tuser account. Modify the ServerInfo configuration section to run\n"
182 "\tthe server as non-root user.\n");
186 SILC_LOG_DEBUG(("Changing to group %s (gid=%u)", group, gr->gr_gid));
187 if (setgid(gr->gr_gid) != 0) {
188 fprintf(stderr, "Error: Failed setgid() to %s (gid=%u). Exiting.\n",
192 #if defined HAVE_SETGROUPS && defined HAVE_INITGROUPS
193 SILC_LOG_DEBUG(("Removing supplementary groups"));
194 if (setgroups(0, NULL) != 0) {
195 fprintf(stderr, "Error: Failed setgroups() to NULL. Exiting.\n");
198 SILC_LOG_DEBUG(("Setting supplementary groups for user %s", user));
199 if (initgroups(user, gr->gr_gid) != 0) {
200 fprintf(stderr, "Error: Failed initgroups() for user %s (gid=%u). "
201 "Exiting.\n", user, gr->gr_gid);
205 SILC_LOG_DEBUG(("Changing to user %s (uid=%u)", user, pw->pw_uid));
206 if (setuid(pw->pw_uid) != 0) {
207 fprintf(stderr, "Error: Failed to setuid() to %s (gid=%u). Exiting.\n",
214 /* Fork server to background */
216 static void silc_server_daemonise(SilcServer server)
220 SILC_LOG_DEBUG(("Forking SILC server to background"));
222 if ((i = fork()) < 0) {
223 fprintf(stderr, "Error: fork() failed: %s\n", strerror(errno));
227 if (i) /* Kill the parent */
230 server->background = TRUE;
233 /* XXX close stdin, stdout, stderr -- before this, check that all writes
234 to stderr are changed to SILC_SERVER_LOG_ERROR() */
237 static void signal_handler(int sig)
239 /* Mark the signal to be caller after this signal is over. */
240 silc_schedule_signal_call(silcd->schedule, sig);
243 SILC_TASK_CALLBACK(got_hup)
245 /* First, reset all log files (they might have been deleted) */
246 silc_log_reset_all();
248 /* Rehash the configuration file */
249 silc_server_rehash(silcd);
252 SILC_TASK_CALLBACK(stop_server)
254 /* Stop scheduler, the program will stop eventually after noticing
255 that the scheduler is down. */
256 silc_schedule_stop(silcd->schedule);
259 /* Dump server statistics into a file into /tmp directory */
261 SILC_TASK_CALLBACK(dump_stats)
267 memset(filename, 0, sizeof(filename));
268 snprintf(filename, sizeof(filename) - 1, "/tmp/silcd.%d.stats-XXXXXX", getpid());
269 fild = mkstemp(filename);
273 fdd = fdopen(fild, "w");
280 #define STAT_OUTPUT(fmt, stat) fprintf(fdd, fmt "\n", (int)stat);
282 fprintf(fdd, "SILC Server %s Statistics\n\n", silcd->server_name);
283 fprintf(fdd, "Local Stats:\n");
284 STAT_OUTPUT(" My clients : %d", silcd->stat.my_clients);
285 STAT_OUTPUT(" My servers : %d", silcd->stat.my_servers);
286 STAT_OUTPUT(" My routers : %d", silcd->stat.my_routers);
287 STAT_OUTPUT(" My channels : %d", silcd->stat.my_channels);
288 STAT_OUTPUT(" My joined users : %d", silcd->stat.my_chanclients);
289 STAT_OUTPUT(" My aways : %d", silcd->stat.my_aways);
290 STAT_OUTPUT(" My detached clients : %d", silcd->stat.my_detached);
291 STAT_OUTPUT(" My server operators : %d", silcd->stat.my_server_ops);
292 STAT_OUTPUT(" My router operators : %d", silcd->stat.my_router_ops);
293 fprintf(fdd, "\nGlobal Stats:\n");
294 STAT_OUTPUT(" Cell clients : %d", silcd->stat.cell_clients);
295 STAT_OUTPUT(" Cell servers : %d", silcd->stat.cell_servers);
296 STAT_OUTPUT(" Cell channels : %d", silcd->stat.cell_channels);
297 STAT_OUTPUT(" Cell joined users : %d", silcd->stat.cell_chanclients);
298 STAT_OUTPUT(" All clients : %d", silcd->stat.clients);
299 STAT_OUTPUT(" All servers : %d", silcd->stat.servers);
300 STAT_OUTPUT(" All routers : %d", silcd->stat.routers);
301 STAT_OUTPUT(" All channels : %d", silcd->stat.channels);
302 STAT_OUTPUT(" All joined users : %d", silcd->stat.chanclients);
303 STAT_OUTPUT(" All aways : %d", silcd->stat.aways);
304 STAT_OUTPUT(" All detached clients : %d", silcd->stat.detached);
305 STAT_OUTPUT(" All server operators : %d", silcd->stat.server_ops);
306 STAT_OUTPUT(" All router operators : %d", silcd->stat.router_ops);
307 fprintf(fdd, "\nGeneral Stats:\n");
308 STAT_OUTPUT(" Connection attempts : %d", silcd->stat.conn_attempts);
309 STAT_OUTPUT(" Connection failures : %d", silcd->stat.conn_failures);
310 STAT_OUTPUT(" Authentication attempts : %d", silcd->stat.auth_attempts);
311 STAT_OUTPUT(" Authentication failures : %d", silcd->stat.auth_failures);
312 STAT_OUTPUT(" Packets sent : %d", silcd->stat.packets_sent);
313 STAT_OUTPUT(" Packets received : %d", silcd->stat.packets_received);
314 STAT_OUTPUT(" Commands sent : %d", silcd->stat.commands_sent);
315 STAT_OUTPUT(" Commands received : %d", silcd->stat.commands_received);
316 STAT_OUTPUT(" Connections : %d", silcd->stat.conn_num);
321 /* Dump internal flags */
322 fprintf(fdd, "\nDumping internal flags\n");
323 fprintf(fdd, " server_type : %d\n", silcd->server_type);
324 fprintf(fdd, " standalone : %d\n", silcd->standalone);
325 fprintf(fdd, " listenning : %d\n", silcd->listenning);
326 fprintf(fdd, " background : %d\n", silcd->background);
327 fprintf(fdd, " backup_router : %d\n", silcd->backup_router);
328 fprintf(fdd, " backup_primary : %d\n", silcd->backup_primary);
329 fprintf(fdd, " backup_noswitch : %d\n", silcd->backup_noswitch);
330 fprintf(fdd, " backup_closed : %d\n", silcd->backup_closed);
331 fprintf(fdd, " wait_backup : %d\n", silcd->wait_backup);
333 fprintf(fdd, " primary router : %s\n",
334 silcd->router->server_name ? silcd->router->server_name : "");
336 /* Dump socket connections */
339 SilcSocketConnection s;
341 fprintf(fdd, "\nDumping socket connections\n");
342 for (i = 0; i < silcd->config->param.connections_max; i++) {
343 s = silcd->sockets[i];
346 fprintf(fdd, " %d: host %s ip %s port %d type %d flags 0x%x\n",
347 s->sock, s->hostname ? s->hostname : "N/A",
348 s->ip ? s->ip : "N/A", s->port, s->type,
349 (unsigned int)s->flags);
355 SilcIDCacheList list = NULL;
356 SilcIDCacheEntry id_cache = NULL;
357 SilcServerEntry server_entry;
358 SilcClientEntry client_entry;
359 SilcChannelEntry channel_entry;
362 fprintf(fdd, "\nDumping databases\n");
364 if (silc_idcache_get_all(silcd->local_list->servers, &list)) {
365 if (silc_idcache_list_first(list, &id_cache)) {
366 fprintf(fdd, "\nServers in local-list:\n");
369 server_entry = (SilcServerEntry)id_cache->context;
370 fprintf(fdd, " %d: name %s id %s status 0x%x\n", c,
371 server_entry->server_name ? server_entry->server_name :
372 "N/A", server_entry->id ?
373 silc_id_render(server_entry->id, SILC_ID_SERVER) : "N/A",
374 server_entry->data.status);
375 if (!silc_idcache_list_next(list, &id_cache))
380 silc_idcache_list_free(list);
382 if (silc_idcache_get_all(silcd->global_list->servers, &list)) {
383 if (silc_idcache_list_first(list, &id_cache)) {
384 fprintf(fdd, "\nServers in global-list:\n");
387 server_entry = (SilcServerEntry)id_cache->context;
388 fprintf(fdd, " %d: name %s id %s status 0x%x\n", c,
389 server_entry->server_name ? server_entry->server_name :
390 "N/A", server_entry->id ?
391 silc_id_render(server_entry->id, SILC_ID_SERVER) : "N/A",
392 server_entry->data.status);
393 if (!silc_idcache_list_next(list, &id_cache))
398 silc_idcache_list_free(list);
400 if (silc_idcache_get_all(silcd->local_list->clients, &list)) {
401 if (silc_idcache_list_first(list, &id_cache)) {
402 fprintf(fdd, "\nClients in local-list:\n");
405 client_entry = (SilcClientEntry)id_cache->context;
406 server_entry = client_entry->router;
407 fprintf(fdd, " %d: name %s id %s status 0x%x from %s\n", c,
408 client_entry->nickname ? client_entry->nickname :
409 (unsigned char *)"N/A", client_entry->id ?
410 silc_id_render(client_entry->id, SILC_ID_CLIENT) : "N/A",
411 client_entry->data.status, server_entry ?
412 server_entry->server_name ? server_entry->server_name :
414 if (!silc_idcache_list_next(list, &id_cache))
419 silc_idcache_list_free(list);
421 if (silc_idcache_get_all(silcd->global_list->clients, &list)) {
422 if (silc_idcache_list_first(list, &id_cache)) {
423 fprintf(fdd, "\nClients in global-list:\n");
426 client_entry = (SilcClientEntry)id_cache->context;
427 server_entry = client_entry->router;
428 fprintf(fdd, " %d: name %s id %s status 0x%x from %s\n", c,
429 client_entry->nickname ? client_entry->nickname :
430 (unsigned char *)"N/A", client_entry->id ?
431 silc_id_render(client_entry->id, SILC_ID_CLIENT) : "N/A",
432 client_entry->data.status, server_entry ?
433 server_entry->server_name ? server_entry->server_name :
435 if (!silc_idcache_list_next(list, &id_cache))
440 silc_idcache_list_free(list);
442 if (silc_idcache_get_all(silcd->local_list->channels, &list)) {
443 if (silc_idcache_list_first(list, &id_cache)) {
444 fprintf(fdd, "\nChannels in local-list:\n");
447 channel_entry = (SilcChannelEntry)id_cache->context;
448 fprintf(fdd, " %d: name %s id %s\n", c,
449 channel_entry->channel_name ? channel_entry->channel_name :
450 "N/A", channel_entry->id ?
451 silc_id_render(channel_entry->id, SILC_ID_CHANNEL) : "N/A");
452 if (!silc_idcache_list_next(list, &id_cache))
457 silc_idcache_list_free(list);
459 if (silc_idcache_get_all(silcd->global_list->channels, &list)) {
460 if (silc_idcache_list_first(list, &id_cache)) {
461 fprintf(fdd, "\nChannels in global-list:\n");
464 channel_entry = (SilcChannelEntry)id_cache->context;
465 fprintf(fdd, " %d: name %s id %s\n", c,
466 channel_entry->channel_name ? channel_entry->channel_name :
467 "N/A", channel_entry->id ?
468 silc_id_render(channel_entry->id, SILC_ID_CHANNEL) : "N/A");
469 if (!silc_idcache_list_next(list, &id_cache))
474 silc_idcache_list_free(list);
490 static DebugLevel debug_levels[] = {
491 /* Very basic stuff from silcd/ */
492 { 3, "silcd\\.c,server\\.c" },
494 /* More stuff from silcd/ */
495 { 7, "silcd\\.c,server\\.c,command\\.c,server_backup\\.c,packet_send\\.c" },
497 /* All basic stuff from silcd/ */
498 { 10, "silc_server_*" },
500 /* All from silcd/ */
501 { 15, "*silcd*,*serverid*,silc_server_*,*idlist*" },
503 /* All from silcd/ and basic stuff from libs */
504 { 20, "*silcd*,*serverid*,silc_server_*,*idlist*,*silcauth*,*silcske*" },
506 /* All from silcd/ and more stuff from libs */
507 { 25, "*silcd*,*serverid*,silc_server_*,*idlist*,*silcauth*,"
508 "*silcpacket*,*ske*,*silcrng*" },
510 /* All from silcd/ and even more stuff from libs */
511 { 30, "*silcd*,*serverid*,silc_server_*,*idlist*,*silcauth*,"
512 "*silcpacket*,*ske*,*silcrng*,*command*,*channel*,*private*,*notify*" },
514 /* All from silcd/ and even more stuff from libs + all from silccore */
515 { 35, "*silcd*,*serverid*,silc_server_*,*idlist*,*silcauth*,"
516 "*silcpacket*,*ske*,*silcrng*,*command*,*channel*,*private*,*notify*"
517 "*silcid*,*argument*" },
519 /* All from silcd/, all from silccore, silccrypt and silcmath */
520 { 40, "*silcd*,*serverid*,silc_server_*,*idlist*,*silcauth*,"
521 "*silcpacket*,*ske*,*silcrng*,*command*,*channel*,*private*,*notify*"
522 "*silcid*,*argument*,*pkcs*,*hmac*,*hash*,*cipher*,silc_math*" },
524 /* All from silcd/, all from silccore, silccrypt and silcmath + stuff
526 { 45, "*silcd*,*serverid*,silc_server_*,*idlist*,*silcauth*,"
527 "*silcpacket*,*ske*,*silcrng*,*command*,*channel*,*private*,*notify*"
528 "*silcid*,*argument*,*pkcs*,*hmac*,*hash*,*cipher*,silc_math*,*sim*"
531 /* All from silcd/, all from silccore, silccrypt and silcmath + more stuff
533 { 50, "*silcd*,*serverid*,silc_server_*,*idlist*,*silcauth*,"
534 "*silcpacket*,*ske*,*silcrng*,*command*,*channel*,*private*,*notify*"
535 "*silcid*,*argument*,*pkcs*,*hmac*,*hash*,*cipher*,silc_math*,*sim*"
536 "*sockconn*,*net*" },
538 /* All from silcd/, all from silccore, silccrypt and silcmath + more stuff
540 { 55, "*silcd*,*serverid*,silc_server_*,*idlist*,*silcauth*,"
541 "*silcpacket*,*ske*,*silcrng*,*command*,*channel*,*private*,*notify*"
542 "*silcid*,*argument*,*pkcs*,*hmac*,*hash*,*cipher*,silc_math*,*sim*"
543 "*sockconn*,*net*,*log*,*config*" },
551 static void silc_get_debug_level(int level)
558 for (i = 0; debug_levels[i].string; i++)
559 if (level <= debug_levels[i].level) {
560 silc_log_set_debug_string(debug_levels[i].string);
564 #endif /* SILC_DEBUG */
566 /* This function should not be called directly but through the appropriate
567 wrapper macro defined in server.h */
569 void silc_server_stderr(SilcLogType type, char *message)
571 if (silcd->background) {
572 char *p, *n = message;
574 /* remove newlines if we are going to output it to a log file */
575 for (p = n; *p; p++) {
584 /* the message is freed inside the logging function */
585 silc_log_output(type, message);
588 fprintf(stderr, "%s\n", message);
593 int main(int argc, char **argv)
595 int ret, opt, option_index;
596 bool foreground = FALSE;
597 bool opt_create_keypair = FALSE;
598 char *silcd_config_file = NULL;
601 /* Parse command line arguments */
603 #ifdef HAVE_GETOPT_LONG
604 while ((opt = getopt_long(argc, argv, "f:p:d:D:xhFVC:",
605 long_opts, &option_index)) != EOF) {
607 while ((opt = getopt(argc, argv, "f:p:d:D:xhFVC:")) != EOF) {
608 #endif /* HAVE_GETOPT_LONG */
614 printf("SILCd Secure Internet Live Conferencing daemon, "
615 "version %s (base: SILC Toolkit %s)\n",
616 silc_dist_version, silc_version);
617 printf("(c) 1997 - 2005 Pekka Riikonen "
618 "<priikone@silcnet.org>\n");
623 silc_log_debug(TRUE);
624 silc_log_quick(TRUE);
626 silc_log_set_debug_string(optarg);
627 foreground = TRUE; /* implied */
630 "Run-time debugging is not enabled. To enable it recompile\n"
631 "the server with --enable-debug configuration option.\n");
636 silc_log_debug(TRUE);
637 silc_log_quick(TRUE);
639 silc_get_debug_level(atoi(optarg));
640 foreground = TRUE; /* implied */
643 "Run-time debugging is not enabled. To enable it recompile\n"
644 "the server with --enable-debug configuration option.\n");
649 silc_log_debug(TRUE);
650 silc_log_debug_hexdump(TRUE);
651 silc_log_quick(TRUE);
652 foreground = TRUE; /* implied */
655 "Run-time debugging is not enabled. To enable it recompile\n"
656 "the server with --enable-debug configuration option.\n");
660 silcd_config_file = strdup(optarg);
667 * Key management options
670 opt_create_keypair = TRUE;
672 opt_keypath = strdup(optarg);
676 opt_pkcs = strdup(optarg);
680 opt_bits = atoi(optarg);
684 opt_identifier = strdup(optarg);
694 if (opt_create_keypair == TRUE) {
695 /* Create new key pair and exit */
696 char pubfile[256], prvfile[256];
698 memset(pubfile, 0, sizeof(pubfile));
699 memset(prvfile, 0, sizeof(prvfile));
700 snprintf(pubfile, sizeof(pubfile) - 1, "%s/silcd.pub", opt_keypath);
701 snprintf(prvfile, sizeof(prvfile) - 1, "%s/silcd.prv", opt_keypath);
703 silc_cipher_register_default();
704 silc_pkcs_register_default();
705 silc_hash_register_default();
706 silc_hmac_register_default();
707 silc_create_key_pair(opt_pkcs, opt_bits, pubfile, prvfile,
708 opt_identifier, "", NULL, NULL, NULL, FALSE);
712 /* Default configuration file */
713 if (!silcd_config_file)
714 silcd_config_file = strdup(SILC_SERVER_CONFIG_FILE);
716 /* Create SILC Server object */
717 ret = silc_server_alloc(&silcd);
721 /* Register default crypto stuff since we are going to need them
722 in the configuration file parsing phase */
723 silc_cipher_register_default();
724 silc_pkcs_register_default();
725 silc_hash_register_default();
726 silc_hmac_register_default();
728 /* Read configuration files */
729 silcd->config = silc_server_config_alloc(silcd_config_file);
730 if (silcd->config == NULL)
732 silcd->config_file = silcd_config_file;
734 /* Unregister the default crypto stuff so that configuration takes effect */
735 silc_cipher_unregister_all();
736 silc_pkcs_unregister_all();
737 silc_hash_unregister_all();
738 silc_hmac_unregister_all();
740 /* Check for another silcd running */
741 silc_server_checkpid(silcd);
743 /* Initialize the server */
744 if (silc_server_init(silcd) == FALSE)
747 /* Ignore some signals */
748 sa.sa_handler = SIG_IGN;
750 sigemptyset(&sa.sa_mask);
752 sigaction(SIGPIPE, &sa, NULL); /* Ignore broken pipes */
755 sigaction(SIGXFSZ, &sa, NULL); /* Ignore file limit exceeds */
758 sigaction(SIGXCPU, &sa, NULL); /* Ignore CPU time limit exceeds */
761 /* Handle specificly some other signals. */
762 sa.sa_handler = signal_handler;
763 sigaction(SIGHUP, &sa, NULL);
764 sigaction(SIGTERM, &sa, NULL);
765 sigaction(SIGINT, &sa, NULL);
766 sigaction(SIGUSR1, &sa, NULL);
767 silc_schedule_signal_register(silcd->schedule, SIGHUP, got_hup, NULL);
768 silc_schedule_signal_register(silcd->schedule, SIGTERM, stop_server, NULL);
769 silc_schedule_signal_register(silcd->schedule, SIGINT, stop_server, NULL);
770 silc_schedule_signal_register(silcd->schedule, SIGUSR1, dump_stats, NULL);
773 /* Before running the server, fork to background. */
774 silc_server_daemonise(silcd);
776 /* If set, write pid to file */
777 if (silcd->config->server_info->pid_file) {
778 char buf[10], *pidfile = silcd->config->server_info->pid_file;
780 snprintf(buf, sizeof(buf) - 1, "%d\n", getpid());
781 silc_file_writefile(pidfile, buf, strlen(buf));
784 silc_server_drop_privs(silcd);
787 /* Run the server. When this returns the server has been stopped
789 silc_server_run(silcd);
791 /* Stop the server and free it. */
792 silc_server_stop(silcd);
793 silc_server_config_destroy(silcd->config);
794 silc_server_free(silcd);
796 /* Flush the logging system */
797 silc_log_flush_all();
799 silc_free(silcd_config_file);
800 silc_free(opt_identifier);
801 silc_free(opt_keypath);
805 silc_free(silcd_config_file);
806 silc_free(opt_identifier);
807 silc_free(opt_keypath);