Implemented the configuration file for starting the services.
There are also parameters for future capabilities.
--- 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();
}