Added UDP output.
authorviric@mandarina
Sun, 14 May 2006 21:11:29 +0200
changeset 35 6b6bbc8a5fdb
parent 34 2a0cd1ef075c
child 36 c6f7b56729d9
Added UDP output.
Makefile.common
TODO.txt
out_udp.c
syslog.conf
syslog.h
syslog_kernel.c
--- a/Makefile.common	Sun May 14 21:10:26 2006 +0200
+++ b/Makefile.common	Sun May 14 21:11:29 2006 +0200
@@ -16,13 +16,14 @@
 syslog_in_unix.o: syslog_in_unix.c rfc3164.h syslog.h
 syslog_kernel.o: syslog_kernel.c rfc3164.h syslog.h
 config.o: syslog.h
+out_udp.o: syslog.h
 signals.o: syslog.h
 
 syslog_in_npipe: syslog_in_npipe.o rfc3164.a signals.o
 syslog_in_udp: syslog_in_udp.o rfc3164.a signals.o
 syslog_in_unix: syslog_in_unix.o rfc3164.a signals.o
 unix_writer: unix_writer.o
-syslog_kernel: syslog_kernel.o config.o rfc3164.a signals.o
+syslog_kernel: syslog_kernel.o config.o rfc3164.a signals.o out_udp.o
 
 clean:
 	rm -f *.o *.a
--- a/TODO.txt	Sun May 14 21:10:26 2006 +0200
+++ b/TODO.txt	Sun May 14 21:11:29 2006 +0200
@@ -2,5 +2,9 @@
 * Fer que in_npipe crei la named pipe?
 * establir els permisos del unix socket
 
-snprintf
-ranlib
+* Implementar la sortida UDP.
+* Implementar el HUP al kernel - rellegir la configuració.
+* Implementar catxé de log-file amb SIGUSR1 associat. (De veritat?!)
+  I won't do that for this release.
+* Implementar una mort neta dels childs (SIGTERM) i el kernel.
+  Done in kernel and in_unix. The others die quite fine.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/out_udp.c	Sun May 14 21:11:29 2006 +0200
@@ -0,0 +1,123 @@
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netdb.h>
+#include <string.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include "syslog.h"
+
+/* Prototypes */
+static int init_socket(const char * restrict node,
+		const char * restrict service);
+
+/* Local globals */
+static int out_socket;
+static bool socket_enabled = false;
+
+
+/* Returns -2 when the socket wasn't initialized by config, 0 when all was ok,
+ * -1 on more important error */
+int init_out_udp()
+{
+	char node[MAX_STRING];
+	char service[MAX_STRING];
+
+	/* Get the configuration */
+	get_config(TO_UDP_HOST, node, MAX_STRING);
+	get_config(TO_UDP_PORT, service, MAX_STRING);
+
+	if (strncmp(node, "disabled", MAX_STRING) == 0)
+		return -2;
+
+	if (strncmp(service, "disabled", MAX_STRING) == 0)
+		return -2;
+
+	return init_socket(node, service);
+}
+
+/* Returns -2 when the socket wasn't initialized by config, 0 when all was ok,
+ * -1 on more important error */
+static int init_socket(const char * restrict node,
+		const char * restrict service)
+{
+	int res;
+	struct addrinfo *addr_res, *ptr;
+	struct addrinfo hints;
+
+	/* Prepare the hints for datagram */
+	memset(&hints, 0, sizeof(hints));
+	hints.ai_flags = AI_ADDRCONFIG;
+	hints.ai_family = AF_UNSPEC;
+	hints.ai_socktype = SOCK_DGRAM;
+	hints.ai_addr = NULL;
+	hints.ai_canonname = NULL;
+	hints.ai_next = NULL;
+
+	/* Ask the system for the service */
+	res = getaddrinfo(node, service, &hints, &addr_res);
+	if (res != 0)
+	{
+		fprintf(stderr, "Error trying to resolve the out_udp"
+				" name: %s\n", gai_strerror(res));
+		if (res == EAI_SYSTEM)
+		{
+			fprintf(stderr, " More system info: %s\n",
+					strerror(errno));
+		}
+		return -1;
+	}
+
+	ptr = addr_res;
+	do
+	{
+		res = -1; /* For further error catching */
+		out_socket = socket(ptr->ai_family, ptr->ai_socktype,
+				ptr->ai_protocol);
+		if (out_socket == -1)
+			continue;
+		res = connect(out_socket, ptr->ai_addr, ptr->ai_addrlen);
+		if (res == 0)
+		{
+			break;
+		}
+		else /* Unsuccesful connect */
+		{
+			close(out_socket);
+			continue;
+		}
+
+	} while((ptr = ptr->ai_next) != NULL);
+
+	freeaddrinfo(addr_res);
+
+	/* If everything is fine */
+	if (res == 0)
+	{
+		socket_enabled = true;
+	}
+
+	return res;
+}
+
+
+/* Return -2 when the socket is not enabled. Otherwise, the output of send().*/
+int write_out_udp(const char *buf, const int len)
+{
+	if (!socket_enabled)
+		return -2;
+
+	return send(out_socket, buf, len, 0);
+}
+
+/* Return -2 when the socket is not enabled. Otherwise, the output of close().*/
+int close_out_udp()
+{
+	if (!socket_enabled)
+		return -2;
+
+	return close(out_socket);
+	
+}
--- a/syslog.conf	Sun May 14 21:10:26 2006 +0200
+++ b/syslog.conf	Sun May 14 21:11:29 2006 +0200
@@ -1,2 +1,4 @@
 from_unix=patata
+to_udp_host=localhost
+to_udp_port=8000
 log_file=prova.log
--- a/syslog.h	Sun May 14 21:10:26 2006 +0200
+++ b/syslog.h	Sun May 14 21:11:29 2006 +0200
@@ -31,3 +31,8 @@
 void program_child_handler(void (*child_handler)(int));
 void program_ignore_hup();
 void program_handler(int signum, void (*handler)(int));
+
+/* out_udp.c */
+int init_out_udp();
+int write_out_udp(const char *buf, const int len);
+int close_out_udp();
--- a/syslog_kernel.c	Sun May 14 21:10:26 2006 +0200
+++ b/syslog_kernel.c	Sun May 14 21:11:29 2006 +0200
@@ -177,8 +177,8 @@
 {
 	int input_pipe[2];
 	char missatge[MESSAGE_LENGTH+1];
-	int res_r, res_w; /* resultats de la crida read i write */
-	int errno_r;  /* errno de la crida read */
+	int res_r, res_w, res_u; /* resultats de la crida read, write, w_udp */
+	int errno_r, errno_w, errno_u;  /* errno de les crides */
 	int output;
 	char value[MAX_STRING];
 
@@ -206,10 +206,13 @@
 		errno_r = errno;
 
 		res_w = 1; /* To bypass further error checking */
+		res_u = 1; /* To bypass further error checking */
 		if (res_r > 0)
 		{
 			/* Add a ZERO for displaying */
 			missatge[res_r] = '\0';
+
+			/* Output to screen */
 			fprintf(stderr, "Received: %s\n",missatge);
 			do
 			{
@@ -221,14 +224,36 @@
 			while(res_w == -1 && errno == EINTR);
 
 			if (res_w == -1 || res_w == 0)
+			{
+				errno_w = errno;
 				break;
+			}
+
+			/* Output to UDP */
+			/* The \0 end is not sent */
+			do
+			{
+				res_u = write_out_udp(missatge, res_r);
+				if (res_u == res_r)
+					break;
+			}
+			/* Protect against EINTR */
+			while(res_u == -1 && errno == EINTR);
+
+			if (res_u == -1 || res_u == 0)
+			{
+				errno_u = errno;
+				break;
+			}
 		}
 		else if (res_r == -1 && errno == EINTR)
+		{
 			/* The call was interrupted by a signal */
 			if (childs_alive == 0)
 				break;
 			else
 				continue;
+		}
 		else /* End of read: res_r -1 or 0 */
 			break;
 	}
@@ -243,10 +268,17 @@
 	if (res_w == -1)
 	{
 		fprintf(stderr, "Error writing to the log file: %s\n", 
-			strerror(errno));
+			strerror(errno_w));
 	} else if (res_w == 0)
 		fprintf(stderr,"Cannot write anymore to the log file.");
 
+	if (res_u == -1)
+	{
+		fprintf(stderr, "Error writing to the UDP socket: %s\n", 
+			strerror(errno_u));
+	} else if (res_w == 0)
+		fprintf(stderr,"Cannot write anymore to the UDP socket.");
+
 	close(output);
 }
 
@@ -299,13 +331,23 @@
 
 int main(int argn, char *argv[])
 {
+	int res;
+
 	install_signal_handlers();
 
 	init_config();
 
+	res = init_out_udp();
+	if (res == -2)
+		fprintf(stderr, "UDP output not in configuration.\n");
+	else if (res == -1)
+		fprintf(stderr, "error setting up the UDP output.\n");
+
 	kernel_loop();
 
 	term_childs();
 
 	wait_childs_die();
+	
+	close_out_udp();
 }