changeset 1339:e70ce64ce689

freeDiameterd: support syslog() logging. Written for Effortel Technologies SA, published with their consent.
author Thomas Klausner <tk@giga.or.at>
date Tue, 09 Apr 2019 15:49:17 +0200
parents f1b65381c1e7
children daf61e573fee
files freeDiameterd/main.c
diffstat 1 files changed, 78 insertions(+), 34 deletions(-) [+]
line wrap: on
line diff
--- a/freeDiameterd/main.c	Tue Apr 09 15:48:45 2019 +0200
+++ b/freeDiameterd/main.c	Tue Apr 09 15:49:17 2019 +0200
@@ -33,13 +33,18 @@
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.								 *
 *********************************************************************************************************/
 
+#if defined(__GLIBC__)
+#define _BSD_SOURCE /* for vsyslog */
+#endif
+
 #include <freeDiameter/freeDiameter-host.h>
 #include <freeDiameter/libfdcore.h>
 
 #include <signal.h>
 #include <getopt.h>
 #include <locale.h>
-
+#include <syslog.h>
+#include <stdarg.h>
 
 /* forward declarations */
 static int main_cmdline(int argc, char *argv[]);
@@ -55,56 +60,86 @@
 }
 
 
+static void syslog_logger(int loglevel, const char * format, va_list args)
+{
+	int level;
+
+	switch (loglevel) {
+	case FD_LOG_NOTICE:
+		level = LOG_NOTICE;
+		break;
+	case FD_LOG_ERROR:
+		level = LOG_ERR;
+		break;
+	case FD_LOG_FATAL:
+		level = LOG_CRIT;
+		break;
+	default:
+		/* fallthrough */
+	case FD_LOG_DEBUG:
+		/* some systems log LOG_DEBUG to a file; but
+		 * freeDiameter debug output is too verbose */
+		return;
+#if 0
+		level = LOG_DEBUG;
+		break;
+#endif
+	}
+
+	vsyslog(level, format, args);
+}
+
+
 /* freeDiameter starting point */
 int main(int argc, char * argv[])
 {
 	int ret;
 	sigset_t sig_all;
-	
+
 	/* Block all signals from the current thread and all its future children -- we will catch everything in catch_signals */
 	sigfillset(&sig_all);
 	ret = pthread_sigmask(SIG_BLOCK, &sig_all, NULL);
 	ASSERT(ret == 0);
-	
+
 	/* Parse the command-line */
 	ret = main_cmdline(argc, argv);
 	if (ret != 0) {
 		return ret;
 	}
-	
+
 	/* Initialize the core library */
 	ret = fd_core_initialize();
 	if (ret != 0) {
 		fprintf(stderr, "An error occurred during freeDiameter core library initialization.\n");
 		return ret;
 	}
-	
+
 	/* Set gnutls debug level ? */
 	if (gnutls_debug) {
 		gnutls_global_set_log_function((gnutls_log_func)fd_gnutls_debug);
 		gnutls_global_set_log_level (gnutls_debug);
 		TRACE_DEBUG(INFO, "Enabled GNUTLS debug at level %d", gnutls_debug);
 	}
-	
+
 	/* Parse the configuration file */
 	CHECK_FCT_DO( fd_core_parseconf(conffile), goto error );
-	
+
 	/* Start the servers */
 	CHECK_FCT_DO( fd_core_start(), goto error );
-	
+
 	/* Allow SIGINT and SIGTERM from this point to terminate the application */
 	CHECK_POSIX_DO( pthread_create(&signals_thr, NULL, catch_signals, NULL), goto error );
-	
+
 	TRACE_DEBUG(INFO, FD_PROJECT_BINARY " daemon initialized.");
 
 	/* Now, just wait for termination */
 	CHECK_FCT( fd_core_wait_shutdown_complete() );
-	
+
 	/* Just in case it was not the result of a signal, we cancel signals_thr */
 	fd_thr_term(&signals_thr);
-	
+
 	return 0;
-error:	
+error:
 	CHECK_FCT_DO( fd_core_shutdown(),  );
 	CHECK_FCT( fd_core_wait_shutdown_complete() );
 	fd_thr_term(&signals_thr);
@@ -137,7 +172,8 @@
 	printf( "  -h, --help             Print help and exit\n"
   		"  -V, --version          Print version and exit\n"
   		"  -c, --config=filename  Read configuration from this file instead of the \n"
-		"                           default location (" DEFAULT_CONF_PATH "/" FD_DEFAULT_CONF_FILENAME ").\n");
+		"                           default location (" DEFAULT_CONF_PATH "/" FD_DEFAULT_CONF_FILENAME ").\n"
+		"  -s, --syslog            Write log output to syslog (instead of stdout)\n");
  	printf( "\nDebug:\n"
   		"  These options are mostly useful for developers\n"
   		"  -l, --dbglocale         Set the locale for error messages\n"
@@ -155,11 +191,12 @@
 	int c;
 	int option_index = 0;
 	char * locale;
-	
+
       	struct option long_options[] = {
 		{ "help",	no_argument, 		NULL, 'h' },
 		{ "version",	no_argument, 		NULL, 'V' },
 		{ "config",	required_argument, 	NULL, 'c' },
+		{ "syslog",     no_argument,            NULL, 's' },
 		{ "debug",	no_argument, 		NULL, 'd' },
 		{ "quiet",	no_argument, 		NULL, 'q' },
 		{ "dbglocale",	optional_argument, 	NULL, 'l' },
@@ -168,13 +205,13 @@
 		{ "dbg_gnutls",	required_argument, 	NULL, 'g' },
 		{ NULL,		0, 			NULL, 0 }
 	};
-	
+
 	/* Loop on arguments */
 	while (1) {
-		c = getopt_long (argc, argv, "hVc:dql:f:F:g:", long_options, &option_index);
-		if (c == -1) 
+		c = getopt_long (argc, argv, "hVc:dql:f:F:g:s", long_options, &option_index);
+		if (c == -1)
 			break;	/* Exit from the loop.  */
-		
+
 		switch (c) {
 			case 'h':	/* Print help and exit.  */
 				main_help();
@@ -199,11 +236,11 @@
 					return EINVAL;
 				}
 				break;
-				
+
 			case 'd':	/* Increase verbosity of debug messages.  */
 				fd_g_debug_lvl--;
 				break;
-				
+
 			case 'f':	/* Full debug for the function with this name.  */
 				#ifdef DEBUG
 				fd_debug_one_function = optarg;
@@ -213,7 +250,7 @@
 				return EINVAL;
 				#endif /* DEBUG */
 				break;
-				
+
 			case 'F':	/* Full debug for the file with this name.  */
 				#ifdef DEBUG
 				fd_debug_one_file = basename(optarg);
@@ -223,15 +260,22 @@
 				return EINVAL;
 				#endif /* DEBUG */
 				break;
-				
+
 			case 'g':	/* Set a debug level and function for GNU TLS calls.  */
 				gnutls_debug = (int)atoi(optarg);
 				break;
-				
+
 			case 'q':	/* Decrease verbosity then remove debug messages.  */
 				fd_g_debug_lvl++;
 				break;
 
+			case 's':	/* Write log data using syslog(3) */
+				if (fd_log_handler_register(syslog_logger) != 0) {
+					fprintf(stderr, "Cannot initialize syslog logger\n");
+					return EINVAL;
+				}
+				break;
+
 			case '?':	/* Invalid option.  */
 				/* `getopt_long' already printed an error message.  */
 				fprintf(stderr, "getopt_long found an invalid character\n");
@@ -243,7 +287,7 @@
 				return EINVAL;
 		}
 	}
-		
+
 	return 0;
 }
 
@@ -252,29 +296,29 @@
 {
 	sigset_t ss;
 	fd_log_threadname ( "signals catcher" );
-	
+
 	sigemptyset(&ss);
-	
+
 	/* Signals that terminate the daemon */
 	sigaddset(&ss, SIGTERM);
 	sigaddset(&ss, SIGINT);
-	
+
 	/* Signals that send an event */
 	sigaddset(&ss, SIGUSR1);
 	sigaddset(&ss, SIGUSR2);
-	
+
 	/* We unblock all other signals, so that their default handler is used (such as SIGTSTP) */
 	CHECK_SYS_DO( pthread_sigmask( SIG_SETMASK, &ss, NULL ), goto out );
-	
+
 	/* Now loop on the reception of the signal */
 	while (1) {
 		int sig, *ps;
-		
+
 		/* Wait to receive the next signal */
 		CHECK_POSIX_DO( sigwait(&ss, &sig), break );
-		
+
 		TRACE_DEBUG(FULL, "Signal %d caught", sig);
-		
+
 		switch (sig) {
 			case SIGUSR1:
 			case SIGUSR2:
@@ -282,14 +326,14 @@
 				*ps = sig;
 				CHECK_FCT_DO( fd_event_send(fd_g_config->cnf_main_ev, FDEV_TRIGGER, sizeof(int), ps), goto out );
 				break;
-				
+
 			case SIGINT:
 			case SIGTERM:
 				CHECK_FCT_DO( fd_core_shutdown(), goto out );
 
 		}
 	}
-out:	
+out:
 	/* Better way to handle this ? */
 	ASSERT(0);
 	return NULL;
"Welcome to our mercurial repository"