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 fd = mkstemp(filename);
273 fdd = fdopen(fd, "w");
275 #define STAT_OUTPUT(fmt, stat) fprintf(fdd, fmt "\n", (int)stat);
277 fprintf(fdd, "SILC Server %s Statistics\n\n", silcd->server_name);
278 fprintf(fdd, "Local Stats:\n");
279 STAT_OUTPUT(" My clients : %d", silcd->stat.my_clients);
280 STAT_OUTPUT(" My servers : %d", silcd->stat.my_servers);
281 STAT_OUTPUT(" My routers : %d", silcd->stat.my_routers);
282 STAT_OUTPUT(" My channels : %d", silcd->stat.my_channels);
283 STAT_OUTPUT(" My joined users : %d", silcd->stat.my_chanclients);
284 STAT_OUTPUT(" My aways : %d", silcd->stat.my_aways);
285 STAT_OUTPUT(" My detached clients : %d", silcd->stat.my_detached);
286 STAT_OUTPUT(" My server operators : %d", silcd->stat.my_server_ops);
287 STAT_OUTPUT(" My router operators : %d", silcd->stat.my_router_ops);
288 fprintf(fdd, "\nGlobal Stats:\n");
289 STAT_OUTPUT(" Cell clients : %d", silcd->stat.cell_clients);
290 STAT_OUTPUT(" Cell servers : %d", silcd->stat.cell_servers);
291 STAT_OUTPUT(" Cell channels : %d", silcd->stat.cell_channels);
292 STAT_OUTPUT(" Cell joined users : %d", silcd->stat.cell_chanclients);
293 STAT_OUTPUT(" All clients : %d", silcd->stat.clients);
294 STAT_OUTPUT(" All servers : %d", silcd->stat.servers);
295 STAT_OUTPUT(" All routers : %d", silcd->stat.routers);
296 STAT_OUTPUT(" All channels : %d", silcd->stat.channels);
297 STAT_OUTPUT(" All joined users : %d", silcd->stat.chanclients);
298 STAT_OUTPUT(" All aways : %d", silcd->stat.aways);
299 STAT_OUTPUT(" All detached clients : %d", silcd->stat.detached);
300 STAT_OUTPUT(" All server operators : %d", silcd->stat.server_ops);
301 STAT_OUTPUT(" All router operators : %d", silcd->stat.router_ops);
302 fprintf(fdd, "\nGeneral Stats:\n");
303 STAT_OUTPUT(" Connection attempts : %d", silcd->stat.conn_attempts);
304 STAT_OUTPUT(" Connection failures : %d", silcd->stat.conn_failures);
305 STAT_OUTPUT(" Authentication attempts : %d", silcd->stat.auth_attempts);
306 STAT_OUTPUT(" Authentication failures : %d", silcd->stat.auth_failures);
307 STAT_OUTPUT(" Packets sent : %d", silcd->stat.packets_sent);
308 STAT_OUTPUT(" Packets received : %d", silcd->stat.packets_received);
309 STAT_OUTPUT(" Commands sent : %d", silcd->stat.commands_sent);
310 STAT_OUTPUT(" Commands received : %d", silcd->stat.commands_received);
311 STAT_OUTPUT(" Connections : %d", silcd->stat.conn_num);
316 /* Dump internal flags */
317 fprintf(fdd, "\nDumping internal flags\n");
318 fprintf(fdd, " server_type : %d\n", silcd->server_type);
319 fprintf(fdd, " standalone : %d\n", silcd->standalone);
320 fprintf(fdd, " listenning : %d\n", silcd->listenning);
321 fprintf(fdd, " background : %d\n", silcd->background);
322 fprintf(fdd, " backup_router : %d\n", silcd->backup_router);
323 fprintf(fdd, " backup_primary : %d\n", silcd->backup_primary);
324 fprintf(fdd, " backup_noswitch : %d\n", silcd->backup_noswitch);
325 fprintf(fdd, " backup_closed : %d\n", silcd->backup_closed);
326 fprintf(fdd, " wait_backup : %d\n", silcd->wait_backup);
328 fprintf(fdd, " primary router : %s\n",
329 silcd->router->server_name ? silcd->router->server_name : "");
331 /* Dump socket connections */
334 SilcSocketConnection s;
336 fprintf(fdd, "\nDumping socket connections\n");
337 for (i = 0; i < silcd->config->param.connections_max; i++) {
338 s = silcd->sockets[i];
341 fprintf(fdd, " %d: host %s ip %s port %d type %d flags 0x%x\n",
342 s->sock, s->hostname ? s->hostname : "N/A",
343 s->ip ? s->ip : "N/A", s->port, s->type,
344 (unsigned int)s->flags);
350 SilcIDCacheList list = NULL;
351 SilcIDCacheEntry id_cache = NULL;
352 SilcServerEntry server_entry;
353 SilcClientEntry client_entry;
354 SilcChannelEntry channel_entry;
357 fprintf(fdd, "\nDumping databases\n");
359 if (silc_idcache_get_all(silcd->local_list->servers, &list)) {
360 if (silc_idcache_list_first(list, &id_cache)) {
361 fprintf(fdd, "\nServers in local-list:\n");
364 server_entry = (SilcServerEntry)id_cache->context;
365 fprintf(fdd, " %d: name %s id %s status 0x%x\n", c,
366 server_entry->server_name ? server_entry->server_name :
367 "N/A", server_entry->id ?
368 silc_id_render(server_entry->id, SILC_ID_SERVER) : "N/A",
369 server_entry->data.status);
370 if (!silc_idcache_list_next(list, &id_cache))
375 silc_idcache_list_free(list);
377 if (silc_idcache_get_all(silcd->global_list->servers, &list)) {
378 if (silc_idcache_list_first(list, &id_cache)) {
379 fprintf(fdd, "\nServers in global-list:\n");
382 server_entry = (SilcServerEntry)id_cache->context;
383 fprintf(fdd, " %d: name %s id %s status 0x%x\n", c,
384 server_entry->server_name ? server_entry->server_name :
385 "N/A", server_entry->id ?
386 silc_id_render(server_entry->id, SILC_ID_SERVER) : "N/A",
387 server_entry->data.status);
388 if (!silc_idcache_list_next(list, &id_cache))
393 silc_idcache_list_free(list);
395 if (silc_idcache_get_all(silcd->local_list->clients, &list)) {
396 if (silc_idcache_list_first(list, &id_cache)) {
397 fprintf(fdd, "\nClients in local-list:\n");
400 client_entry = (SilcClientEntry)id_cache->context;
401 server_entry = client_entry->router;
402 fprintf(fdd, " %d: name %s id %s status 0x%x from %s\n", c,
403 client_entry->nickname ? client_entry->nickname :
404 (unsigned char *)"N/A", client_entry->id ?
405 silc_id_render(client_entry->id, SILC_ID_CLIENT) : "N/A",
406 client_entry->data.status, server_entry ?
407 server_entry->server_name ? server_entry->server_name :
409 if (!silc_idcache_list_next(list, &id_cache))
414 silc_idcache_list_free(list);
416 if (silc_idcache_get_all(silcd->global_list->clients, &list)) {
417 if (silc_idcache_list_first(list, &id_cache)) {
418 fprintf(fdd, "\nClients in global-list:\n");
421 client_entry = (SilcClientEntry)id_cache->context;
422 server_entry = client_entry->router;
423 fprintf(fdd, " %d: name %s id %s status 0x%x from %s\n", c,
424 client_entry->nickname ? client_entry->nickname :
425 (unsigned char *)"N/A", client_entry->id ?
426 silc_id_render(client_entry->id, SILC_ID_CLIENT) : "N/A",
427 client_entry->data.status, server_entry ?
428 server_entry->server_name ? server_entry->server_name :
430 if (!silc_idcache_list_next(list, &id_cache))
435 silc_idcache_list_free(list);
437 if (silc_idcache_get_all(silcd->local_list->channels, &list)) {
438 if (silc_idcache_list_first(list, &id_cache)) {
439 fprintf(fdd, "\nChannels in local-list:\n");
442 channel_entry = (SilcChannelEntry)id_cache->context;
443 fprintf(fdd, " %d: name %s id %s\n", c,
444 channel_entry->channel_name ? channel_entry->channel_name :
445 "N/A", channel_entry->id ?
446 silc_id_render(channel_entry->id, SILC_ID_CHANNEL) : "N/A");
447 if (!silc_idcache_list_next(list, &id_cache))
452 silc_idcache_list_free(list);
454 if (silc_idcache_get_all(silcd->global_list->channels, &list)) {
455 if (silc_idcache_list_first(list, &id_cache)) {
456 fprintf(fdd, "\nChannels in global-list:\n");
459 channel_entry = (SilcChannelEntry)id_cache->context;
460 fprintf(fdd, " %d: name %s id %s\n", c,
461 channel_entry->channel_name ? channel_entry->channel_name :
462 "N/A", channel_entry->id ?
463 silc_id_render(channel_entry->id, SILC_ID_CHANNEL) : "N/A");
464 if (!silc_idcache_list_next(list, &id_cache))
469 silc_idcache_list_free(list);
485 static DebugLevel debug_levels[] = {
486 /* Very basic stuff from silcd/ */
487 { 3, "silcd\\.c,server\\.c" },
489 /* More stuff from silcd/ */
490 { 7, "silcd\\.c,server\\.c,command\\.c,server_backup\\.c,packet_send\\.c" },
492 /* All basic stuff from silcd/ */
493 { 10, "silc_server_*" },
495 /* All from silcd/ */
496 { 15, "*silcd*,*serverid*,silc_server_*,*idlist*" },
498 /* All from silcd/ and basic stuff from libs */
499 { 20, "*silcd*,*serverid*,silc_server_*,*idlist*,*silcauth*,*silcske*" },
501 /* All from silcd/ and more stuff from libs */
502 { 25, "*silcd*,*serverid*,silc_server_*,*idlist*,*silcauth*,"
503 "*silcpacket*,*ske*,*silcrng*" },
505 /* All from silcd/ and even more stuff from libs */
506 { 30, "*silcd*,*serverid*,silc_server_*,*idlist*,*silcauth*,"
507 "*silcpacket*,*ske*,*silcrng*,*command*,*channel*,*private*,*notify*" },
509 /* All from silcd/ and even more stuff from libs + all from silccore */
510 { 35, "*silcd*,*serverid*,silc_server_*,*idlist*,*silcauth*,"
511 "*silcpacket*,*ske*,*silcrng*,*command*,*channel*,*private*,*notify*"
512 "*silcid*,*argument*" },
514 /* All from silcd/, all from silccore, silccrypt and silcmath */
515 { 40, "*silcd*,*serverid*,silc_server_*,*idlist*,*silcauth*,"
516 "*silcpacket*,*ske*,*silcrng*,*command*,*channel*,*private*,*notify*"
517 "*silcid*,*argument*,*pkcs*,*hmac*,*hash*,*cipher*,silc_math*" },
519 /* All from silcd/, all from silccore, silccrypt and silcmath + stuff
521 { 45, "*silcd*,*serverid*,silc_server_*,*idlist*,*silcauth*,"
522 "*silcpacket*,*ske*,*silcrng*,*command*,*channel*,*private*,*notify*"
523 "*silcid*,*argument*,*pkcs*,*hmac*,*hash*,*cipher*,silc_math*,*sim*"
526 /* All from silcd/, all from silccore, silccrypt and silcmath + more stuff
528 { 50, "*silcd*,*serverid*,silc_server_*,*idlist*,*silcauth*,"
529 "*silcpacket*,*ske*,*silcrng*,*command*,*channel*,*private*,*notify*"
530 "*silcid*,*argument*,*pkcs*,*hmac*,*hash*,*cipher*,silc_math*,*sim*"
531 "*sockconn*,*net*" },
533 /* All from silcd/, all from silccore, silccrypt and silcmath + more stuff
535 { 55, "*silcd*,*serverid*,silc_server_*,*idlist*,*silcauth*,"
536 "*silcpacket*,*ske*,*silcrng*,*command*,*channel*,*private*,*notify*"
537 "*silcid*,*argument*,*pkcs*,*hmac*,*hash*,*cipher*,silc_math*,*sim*"
538 "*sockconn*,*net*,*log*,*config*" },
546 static void silc_get_debug_level(int level)
553 for (i = 0; debug_levels[i].string; i++)
554 if (level <= debug_levels[i].level) {
555 silc_log_set_debug_string(debug_levels[i].string);
559 #endif /* SILC_DEBUG */
561 /* This function should not be called directly but through the appropriate
562 wrapper macro defined in server.h */
564 void silc_server_stderr(SilcLogType type, char *message)
566 if (silcd->background) {
567 char *p, *n = message;
569 /* remove newlines if we are going to output it to a log file */
570 for (p = n; *p; p++) {
579 /* the message is freed inside the logging function */
580 silc_log_output(type, message);
583 fprintf(stderr, "%s\n", message);
588 int main(int argc, char **argv)
590 int ret, opt, option_index;
591 bool foreground = FALSE;
592 bool opt_create_keypair = FALSE;
593 char *silcd_config_file = NULL;
596 /* Parse command line arguments */
598 #ifdef HAVE_GETOPT_LONG
599 while ((opt = getopt_long(argc, argv, "f:p:d:D:xhFVC:",
600 long_opts, &option_index)) != EOF) {
602 while ((opt = getopt(argc, argv, "f:p:d:D:xhFVC:")) != EOF) {
603 #endif /* HAVE_GETOPT_LONG */
609 printf("SILCd Secure Internet Live Conferencing daemon, "
610 "version %s (base: SILC Toolkit %s)\n",
611 silc_dist_version, silc_version);
612 printf("(c) 1997 - 2005 Pekka Riikonen "
613 "<priikone@silcnet.org>\n");
618 silc_log_debug(TRUE);
619 silc_log_quick(TRUE);
621 silc_log_set_debug_string(optarg);
622 foreground = TRUE; /* implied */
625 "Run-time debugging is not enabled. To enable it recompile\n"
626 "the server with --enable-debug configuration option.\n");
631 silc_log_debug(TRUE);
632 silc_log_quick(TRUE);
634 silc_get_debug_level(atoi(optarg));
635 foreground = TRUE; /* implied */
638 "Run-time debugging is not enabled. To enable it recompile\n"
639 "the server with --enable-debug configuration option.\n");
644 silc_log_debug(TRUE);
645 silc_log_debug_hexdump(TRUE);
646 silc_log_quick(TRUE);
647 foreground = TRUE; /* implied */
650 "Run-time debugging is not enabled. To enable it recompile\n"
651 "the server with --enable-debug configuration option.\n");
655 silcd_config_file = strdup(optarg);
662 * Key management options
665 opt_create_keypair = TRUE;
667 opt_keypath = strdup(optarg);
671 opt_pkcs = strdup(optarg);
675 opt_bits = atoi(optarg);
679 opt_identifier = strdup(optarg);
689 if (opt_create_keypair == TRUE) {
690 /* Create new key pair and exit */
691 char pubfile[256], prvfile[256];
693 memset(pubfile, 0, sizeof(pubfile));
694 memset(prvfile, 0, sizeof(prvfile));
695 snprintf(pubfile, sizeof(pubfile) - 1, "%s/silcd.pub", opt_keypath);
696 snprintf(prvfile, sizeof(prvfile) - 1, "%s/silcd.prv", opt_keypath);
698 silc_cipher_register_default();
699 silc_pkcs_register_default();
700 silc_hash_register_default();
701 silc_hmac_register_default();
702 silc_create_key_pair(opt_pkcs, opt_bits, pubfile, prvfile,
703 opt_identifier, "", NULL, NULL, NULL, FALSE);
707 /* Default configuration file */
708 if (!silcd_config_file)
709 silcd_config_file = strdup(SILC_SERVER_CONFIG_FILE);
711 /* Create SILC Server object */
712 ret = silc_server_alloc(&silcd);
716 /* Register default crypto stuff since we are going to need them
717 in the configuration file parsing phase */
718 silc_cipher_register_default();
719 silc_pkcs_register_default();
720 silc_hash_register_default();
721 silc_hmac_register_default();
723 /* Read configuration files */
724 silcd->config = silc_server_config_alloc(silcd_config_file);
725 if (silcd->config == NULL)
727 silcd->config_file = silcd_config_file;
729 /* Unregister the default crypto stuff so that configuration takes effect */
730 silc_cipher_unregister_all();
731 silc_pkcs_unregister_all();
732 silc_hash_unregister_all();
733 silc_hmac_unregister_all();
735 /* Check for another silcd running */
736 silc_server_checkpid(silcd);
738 /* Initialize the server */
739 if (silc_server_init(silcd) == FALSE)
742 /* Ignore some signals */
743 sa.sa_handler = SIG_IGN;
745 sigemptyset(&sa.sa_mask);
747 sigaction(SIGPIPE, &sa, NULL); /* Ignore broken pipes */
750 sigaction(SIGXFSZ, &sa, NULL); /* Ignore file limit exceeds */
753 sigaction(SIGXCPU, &sa, NULL); /* Ignore CPU time limit exceeds */
756 /* Handle specificly some other signals. */
757 sa.sa_handler = signal_handler;
758 sigaction(SIGHUP, &sa, NULL);
759 sigaction(SIGTERM, &sa, NULL);
760 sigaction(SIGINT, &sa, NULL);
761 sigaction(SIGUSR1, &sa, NULL);
762 silc_schedule_signal_register(silcd->schedule, SIGHUP, got_hup, NULL);
763 silc_schedule_signal_register(silcd->schedule, SIGTERM, stop_server, NULL);
764 silc_schedule_signal_register(silcd->schedule, SIGINT, stop_server, NULL);
765 silc_schedule_signal_register(silcd->schedule, SIGUSR1, dump_stats, NULL);
768 /* Before running the server, fork to background. */
769 silc_server_daemonise(silcd);
771 /* If set, write pid to file */
772 if (silcd->config->server_info->pid_file) {
773 char buf[10], *pidfile = silcd->config->server_info->pid_file;
775 snprintf(buf, sizeof(buf) - 1, "%d\n", getpid());
776 silc_file_writefile(pidfile, buf, strlen(buf));
779 silc_server_drop_privs(silcd);
782 /* Run the server. When this returns the server has been stopped
784 silc_server_run(silcd);
786 /* Stop the server and free it. */
787 silc_server_stop(silcd);
788 silc_server_config_destroy(silcd->config);
789 silc_server_free(silcd);
791 /* Flush the logging system */
792 silc_log_flush_all();
794 silc_free(silcd_config_file);
795 silc_free(opt_identifier);
796 silc_free(opt_keypath);
800 silc_free(silcd_config_file);
801 silc_free(opt_identifier);
802 silc_free(opt_keypath);