Implemented the configuration file for starting the services.
authorviric@mandarina
Sat, 13 May 2006 22:16:24 +0200
changeset 21 24714adbc325
parent 20 09734552b307
child 22 52c1a4d0b565
Implemented the configuration file for starting the services. There are also parameters for future capabilities.
.hgignore
Makefile.common
config.c
syslog.conf
syslog.h
syslog_kernel.c
--- a/.hgignore	Sat May 13 10:31:37 2006 +0200
+++ b/.hgignore	Sat May 13 22:16:24 2006 +0200
@@ -3,6 +3,7 @@
 syslog_in_npipe
 syslog_in_udp
 syslog_in_unix
+syslog_kernel
 unix_write
 enunciat/.*\.dvi$
 enunciat/.*\.log$
--- a/Makefile.common	Sat May 13 10:31:37 2006 +0200
+++ b/Makefile.common	Sat May 13 22:16:24 2006 +0200
@@ -14,13 +14,14 @@
 syslog_in_npipe.o: rfc3164.h syslog_in_npipe.c
 syslog_in_udp.o: syslog_in_udp.c rfc3164.h
 syslog_in_unix.o: syslog_in_unix.c rfc3164.h
-syslog_kernel.o: syslog_kernel.c rfc3164.h
+syslog_kernel.o: syslog_kernel.c rfc3164.h syslog.h
+config.o: syslog.h
 
 syslog_in_npipe: syslog_in_npipe.o rfc3164.a
 syslog_in_udp: syslog_in_udp.o rfc3164.a
 syslog_in_unix: syslog_in_unix.o rfc3164.a
 unix_writer: unix_writer.o
-syslog_kernel: syslog_kernel.o rfc3164.a
+syslog_kernel: syslog_kernel.o config.o rfc3164.a
 
 clean:
 	rm -f *.o *.a
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/config.c	Sat May 13 22:16:24 2006 +0200
@@ -0,0 +1,200 @@
+#include <string.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <assert.h>
+#include <errno.h>
+
+#include "syslog.h"
+
+#define CONFIG_FILE "syslog.conf"
+
+/* Data structures */
+
+static struct
+{
+	int n; /* Number of config elements */
+	struct config_element el[ETYPE_END];
+} main_config;
+
+/* Aquesta variable ha de reflexar l'ordre de la enum etype_config de syslog.h*/
+const static struct config_element default_config[ETYPE_END+1] = {
+	{ FROM_UNIX, "unixlog" },
+	{ FROM_NPIPE, "disabled" },
+	{ FROM_UDP, "disabled" },
+	{ TO_UDP_HOST, "localhost" },
+	{ TO_UDP_PORT, "1235" },
+	{ TCP_MANAGER, "1234" },
+	{ LOG_FILE, "file.log" },
+	{ ETYPE_END, "" }};
+
+/* Aquesta variable ha de reflexar l'ordre de la enum etype_config de syslog.h*/
+const static struct {
+	enum etype_config type;
+	char string[MAX_STRING];
+} etype_string[ETYPE_END+1] = {
+	{ FROM_UNIX, "from_unix" },
+	{ FROM_NPIPE, "from_npipe" },
+	{ FROM_UDP, "from_udp" },
+	{ TO_UDP_HOST, "to_udp_host" },
+	{ TO_UDP_PORT, "to_udp_port" },
+	{ TCP_MANAGER, "tcp_manager" },
+	{ LOG_FILE, "log_file" },
+	{ ETYPE_END, "" }};
+
+/* Prototypes */
+static int add_config_element(const char * restrict p, const char * restrict v);
+static void read_config(char * restrict fname);
+
+/* Functions' code */
+
+void init_config()
+{
+	main_config.n = 0;
+	read_config(CONFIG_FILE);
+}
+
+static void read_config(char * restrict fname)
+{
+	int file;
+	char rchar;
+	int res;
+	char parameter[MAX_STRING];
+	int nparameter;
+	char value[MAX_STRING];
+	int nvalue;
+	enum {
+		READ_PARAMETER,
+		READ_VALUE
+	} state;
+
+	file = open(fname, O_RDONLY);
+	if (file == -1)
+	{
+		fprintf(stderr,"The config file cannot be opened");
+		return;
+	}
+
+	nparameter=0;
+	state=READ_PARAMETER;
+	while ((res = read(file, &rchar, 1)) == 1)
+	{
+		switch (rchar)
+		{
+		case '=':
+			assert(nparameter <= MAX_STRING);
+			parameter[nparameter]='\0';
+			nvalue=0;
+			state=READ_VALUE;
+		case '\n':
+			if (state == READ_VALUE)
+			{
+				value[nvalue]='\0';
+				add_config_element(parameter,value);
+			}
+			nparameter=0;
+			nvalue=0;
+			state=READ_PARAMETER;
+		default:
+			switch(state)
+			{
+			case READ_PARAMETER:
+				assert(nparameter <= MAX_STRING);
+				parameter[nparameter++]=rchar;
+			case READ_VALUE:
+				assert(nvalue <= MAX_STRING);
+				value[nvalue++]=rchar;
+			}
+		}
+	}
+
+	if (res == -1)
+	{
+		fprintf(stderr, "Error reading config file: %s",
+				strerror(errno));
+	}
+}
+
+/* Retorna 1 si ha pogut afegir l'element, -1 si hi ha hagut error */
+static int add_config_element(const char * restrict p, const char * restrict v)
+{
+	enum etype_config i, type;
+	int j, pos;
+
+	/* busquem de quin paràmetre es tracta */
+	for(i=0; i<ETYPE_END; i++)
+	{
+		/* a etype_string corresponen índex amb tipus */
+		if (strcmp(p,etype_string[i].string) == 0)
+		{
+			type=i;
+			break;
+		}
+	}
+	if (i==ETYPE_END)
+	{
+		/* Si el paràmetre no és conegut... */
+		return -1;
+	}
+
+	/* Busquem si el paràmetre ja està a la configuració main_config */
+	for (j=0; j<main_config.n; j++)
+	{
+		if(main_config.el[j].type == type)
+		{
+			pos = j;
+			break;
+		}
+	}
+	if(j == main_config.n)
+	{
+		pos = j;
+		main_config.n++;
+		/* At maximum, there should be ETYPE_END elements) */
+		assert(main_config.n <= ETYPE_END);
+	}
+
+	main_config.el[pos].type = type;
+	strcpy(main_config.el[pos].value, v);
+
+	return 1;
+}
+
+/* Returns 2 on configured type, 1 on default value, 0 on disabled,
+ * -1 on error */
+int get_config(const enum etype_config type, char * restrict v)
+{
+	int j;
+	enum {
+		DISABLED=0,
+		DEFAULT=1,
+		CONFIGURED=2,
+		ERROR=-1
+	} ret;
+
+	if (type < 0 || type >= ETYPE_END)
+		return ERROR;
+
+	for (j=0; j<main_config.n; j++)
+	{
+		if(main_config.el[j].type == type)
+		{
+			strcpy(v, main_config.el[j].value);
+			ret = CONFIGURED;
+			break;
+		}
+	}
+
+	if(j == main_config.n)
+	{
+		strcpy(v, default_config[type].value);
+		ret = DEFAULT;
+	}
+
+	if(strcmp(v, "disabled") == 0)
+		return DISABLED;
+	else
+		return ret;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/syslog.h	Sat May 13 22:16:24 2006 +0200
@@ -0,0 +1,29 @@
+enum {
+	MAX_STRING=255
+};
+
+enum etype_config
+{
+	FROM_UNIX,
+	FROM_NPIPE,
+	FROM_UDP,
+	TO_UDP_HOST,
+	TO_UDP_PORT,
+	TCP_MANAGER,
+	LOG_FILE,
+	ETYPE_END
+};
+
+struct config_element
+{
+	enum etype_config type; /* Type of the configuration element */
+	char value[MAX_STRING]; /* Value of the parameter */
+};
+
+
+/* Prototypes -------------------- */
+
+/* config.c */
+
+void init_config();
+int get_config(const enum etype_config type, char * restrict value);
--- a/syslog_kernel.c	Sat May 13 10:31:37 2006 +0200
+++ b/syslog_kernel.c	Sat May 13 22:16:24 2006 +0200
@@ -10,16 +10,30 @@
 #include <stdlib.h> // Per l'abort
 
 #include "rfc3164.h"
+#include "syslog.h"
 
+/* Program names */
 const char syslog_in_unix[] = "syslog_in_unix";
 const char syslog_in_npipe[] = "syslog_in_npipe";
 const char syslog_in_udp[] = "syslog_in_udp";
 
-#define TEST_NPIPE "prova_npipe"
-#define TEST_UDP 4000
-#define TEST_UNIX "prova_unix"
+/* Global variables */
+bool program_initialized = false;
 
-void child_handler(int parameter)
+enum echilds {
+	CHILD_NPIPE,
+	CHILD_UNIX,
+	CHILD_UDP,
+	END_CHILDS
+};
+
+struct {
+	int pid;
+	int input_pipe[2];
+	bool running;
+} child[END_CHILDS];
+
+static void child_handler(int parameter)
 {
 	pid_t pid;
 	int status;
@@ -33,13 +47,13 @@
 			fprintf(stderr, "Child %i died fine:%i\n",
 				pid, WEXITSTATUS(status));
 		} else 
-			fprintf(stderr, "Child %i signaled strange.\n",
-				pid);
+			fprintf(stderr, "Child %i signaled strange: %08x\n",
+				pid, status);
 	} while(pid > 0);
 }
 
-int run_program(const char * restrict programname,
-		const char * restrict parameter1, int comm_pipe[])
+static int run_program(const char * restrict programname,
+		const char * restrict parameter1, const int comm_pipe[])
 {
 	int pid;
 
@@ -52,7 +66,7 @@
 		dup(comm_pipe[0]);
 		dup(comm_pipe[1]);
 		execl(programname, programname, parameter1, NULL);
-		/* Unreachable */
+		/* Unreachable if everything goes well */
 		fprintf(stderr, "Child exec failed(%s %s): %s\n",
 			programname, parameter1, strerror(errno));
 		abort();
@@ -66,58 +80,94 @@
 	}
 }
 
-int init_in_unix(const char * restrict socketname, int input_pipe[])
+static int init_in_unix(const char * restrict socketname,
+		const int input_pipe[2])
 {
 	return run_program(syslog_in_unix, socketname, input_pipe);
 }
 
-int init_in_udp(unsigned int port, int input_pipe[])
+static int init_in_udp(const char * restrict port, const int input_pipe[2])
 {
-	char buffer[20];
-	
-	snprintf(buffer, 20, "%u", port);
-
-	return run_program(syslog_in_udp, buffer, input_pipe);
+	return run_program(syslog_in_udp, port, input_pipe);
 }
 
-int init_in_npipe(const char * restrict pipename, int input_pipe[])
+static int init_in_npipe(const char * restrict pipename,
+		const int input_pipe[2])
 {
 	return run_program(syslog_in_npipe, pipename, input_pipe);
 }
 
-void kernel_loop()
+static void start_childs(const int input_pipe[2])
+{
+	char cvalue[MAX_STRING];
+
+	/* The childs should not run */
+	if (get_config(FROM_UNIX, cvalue) > 0)
+	{
+		child[CHILD_UNIX].input_pipe[0] = input_pipe[0];
+		child[CHILD_UNIX].input_pipe[1] = input_pipe[1];
+		child[CHILD_UNIX].pid = init_in_unix(cvalue, input_pipe);
+		if (child[CHILD_UNIX].pid == 0)
+			child[CHILD_UNIX].running = false;
+		else
+			child[CHILD_UNIX].running = true;
+	}
+
+	if (get_config(FROM_NPIPE, cvalue) > 0)
+	{
+		child[CHILD_NPIPE].input_pipe[0] = input_pipe[0];
+		child[CHILD_NPIPE].input_pipe[1] = input_pipe[1];
+		child[CHILD_NPIPE].pid = init_in_npipe(cvalue, input_pipe);
+		if (child[CHILD_NPIPE].pid == 0)
+			child[CHILD_NPIPE].running = false;
+		else
+			child[CHILD_NPIPE].running = true;
+	}
+
+	if (get_config(FROM_UDP, cvalue) > 0)
+	{
+		child[CHILD_UDP].input_pipe[0] = input_pipe[0];
+		child[CHILD_UDP].input_pipe[1] = input_pipe[1];
+		child[CHILD_UDP].pid = init_in_udp(cvalue, input_pipe);
+		if (child[CHILD_UDP].pid == 0)
+			child[CHILD_UDP].running = false;
+		else
+			child[CHILD_UDP].running = true;
+	}
+}
+
+static void kernel_loop()
 {
 	int input_pipe[2];
 	char missatge[MESSAGE_LENGTH+1];
-	int status;
+	int res;
 
+	/* Pipe for the childs */
 	pipe(input_pipe);
 
-	init_in_npipe(TEST_NPIPE, input_pipe);
-	init_in_udp(TEST_UDP, input_pipe);
-	init_in_unix(TEST_UNIX, input_pipe);
+	start_childs(input_pipe);
 
 	/* We don't want to write to the programs */
 	close(input_pipe[1]);
 
 	while(true)
 	{
-		status = read(input_pipe[0], missatge, MESSAGE_LENGTH);
+		res = read(input_pipe[0], missatge, MESSAGE_LENGTH);
 
-		if (status > 0)
+		if (res > 0)
 		{
 			/* Add a ZERO */
-			missatge[status] = '\0';
+			missatge[res] = '\0';
 			/* The \n is included in the message */
 			printf("Received: %s",missatge);
 		}
-		else if (status == -1 && errno == EINTR)
+		else if (res == -1 && errno == EINTR)
 			continue;
 		else
 			break;
 	}
 
-	if (status == -1)
+	if (res == -1)
 	{
 		printf("Error reading from the main pipe: %s\n", 
 			strerror(errno));
@@ -126,7 +176,7 @@
 
 }
 
-void install_signal_handlers()
+static void install_signal_handlers()
 {
 	struct sigaction my_action;
 	int result;
@@ -139,8 +189,12 @@
 	assert(result == 0);
 }
 
+
 int main(int argn, char *argv[])
 {
 	install_signal_handlers();
+
+	init_config();
+
 	kernel_loop();
 }