diff options
| author | David Oberhollenzer <david.oberhollenzer@tele2.at> | 2018-06-11 16:35:45 +0200 | 
|---|---|---|
| committer | David Oberhollenzer <david.oberhollenzer@tele2.at> | 2018-06-11 19:47:52 +0200 | 
| commit | f1cc12f55ebb51209cb26e71985d35c5e6671520 (patch) | |
| tree | c7e6da98545315f30b9d45669c8503e41dde463a /syslogd | |
| parent | d9f883f2151a026d25277d57d56aa045417dd3bb (diff) | |
[usyslogd] split off syslog parsing
 - Add proto.{h,c} for parsing of syslog message
 - Also parse time stamp in addition to priority
Signed-off-by: David Oberhollenzer <david.oberhollenzer@tele2.at>
Diffstat (limited to 'syslogd')
| -rw-r--r-- | syslogd/Makemodule.am | 1 | ||||
| -rw-r--r-- | syslogd/main.c | 35 | ||||
| -rw-r--r-- | syslogd/proto.c | 177 | ||||
| -rw-r--r-- | syslogd/proto.h | 35 | 
4 files changed, 229 insertions, 19 deletions
diff --git a/syslogd/Makemodule.am b/syslogd/Makemodule.am index 489acc9..9e5378d 100644 --- a/syslogd/Makemodule.am +++ b/syslogd/Makemodule.am @@ -1,5 +1,6 @@  usyslogd_SOURCES = syslogd/main.c  usyslogd_SOURCES += syslogd/logfile.c syslogd/logfile.h +usyslogd_SOURCES += syslogd/proto.c syslogd/proto.h  usyslogd_CPPFLAGS = $(AM_CPPFLAGS)  usyslogd_CFLAGS = $(AM_CFLAGS)  usyslogd_LDFLAGS = $(AM_LDFLAGS) diff --git a/syslogd/main.c b/syslogd/main.c index a5702b7..b1b70b0 100644 --- a/syslogd/main.c +++ b/syslogd/main.c @@ -24,9 +24,9 @@  #include <string.h>  #include <errno.h>  #include <stdio.h> -#include <ctype.h>  #include "logfile.h" +#include "proto.h"  #include "util.h" @@ -118,16 +118,18 @@ static void signal_setup(void)  	sigaction(SIGTERM, &act, NULL);  } -static int print_to_log(int facility, int level, const char *data) +static int print_to_log(const syslog_msg_t *msg)  {  	const char *fac_name, *lvl_str; +	char timebuf[32];  	logfile_t *log; +	struct tm tm; -	fac_name = enum_to_name(facilities, facility); +	fac_name = enum_to_name(facilities, msg->facility);  	if (fac_name == NULL)  		return -1; -	lvl_str = enum_to_name(levels, level); +	lvl_str = enum_to_name(levels, msg->level);  	if (lvl_str == NULL)  		return -1; @@ -144,14 +146,19 @@ static int print_to_log(int facility, int level, const char *data)  		logfiles = log;  	} -	logfile_write(log, "[%s] %s", lvl_str, data); +	gmtime_r(&msg->timestamp, &tm); +	strftime(timebuf, sizeof(timebuf), "%FT%T", &tm); + +	logfile_write(log, "[%s][%s][%s][%u] %s", timebuf, lvl_str, +		      msg->ident ? msg->ident : "", msg->pid, +		      msg->message);  	return 0;  }  static int handle_data(int fd)  { -	char buffer[2048], *ptr; -	int i = 0, priority; +	char buffer[2048]; +	syslog_msg_t msg;  	ssize_t ret;  	memset(buffer, 0, sizeof(buffer)); @@ -160,20 +167,10 @@ static int handle_data(int fd)  	if (ret <= 0)  		return -1; -	for (ptr = buffer; isspace(*ptr); ++ptr) -		; -	if (*(ptr++) != '<') -		return -1; -	if (!isdigit(*ptr)) -		return -1; -	for (priority = 0; isdigit(*ptr); ++ptr) -		priority = priority * 10 + (*ptr) - '0'; -	if (*(ptr++) != '>') +	if (syslog_msg_parse(&msg, buffer))  		return -1; -	while (isspace(*ptr)) -		++ptr; -	return print_to_log(priority >> 3, priority & 0x07, ptr); +	return print_to_log(&msg);  }  int main(void) diff --git a/syslogd/proto.c b/syslogd/proto.c new file mode 100644 index 0000000..3487dbd --- /dev/null +++ b/syslogd/proto.c @@ -0,0 +1,177 @@ +/* SPDX-License-Identifier: GPL-3.0-or-later */ +/* + * Copyright (C) 2018 - David Oberhollenzer + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program.  If not, see <https://www.gnu.org/licenses/>. + */ +#include <stddef.h> +#include <string.h> +#include <ctype.h> +#include <time.h> + +#include "proto.h" + +static const char *months[] = { +	"Jan", "Feb", "Mar", "Apr", +	"May", "Jun", "Jul", "Aug", +	"Sep", "Oct", "Nov", "Dec" +}; + +static const int days[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; + +static int isleap(int year) +{ +	return ((year % 4 == 0) && (year % 100 != 0)) || ((year % 400) == 0); +} + +static int mdays(int year, int month) +{ +	return (isleap(year) && month == 2) ? 29 : days[month - 1]; +} + +static char *read_num(char *str, int *out, int maxval) +{ +	if (str == NULL || !isdigit(*str)) +		return NULL; +	for (*out = 0; isdigit(*str); ++str) { +		(*out) = (*out) * 10 + (*str) - '0'; +		if ((*out) > maxval) +			return NULL; +	} +	return str; +} + +static char *skip_space(char *str) +{ +	if (str == NULL || !isspace(*str)) +		return NULL; +	while (isspace(*str)) +		++str; +	return str; +} + +static char *read_date_bsd(char *str, struct tm *tm) +{ +	int year, month, day, hour, minute, second; +	time_t t; + +	/* decode date */ +	for (month = 0; month < 12; ++month) { +		if (strncmp(str, months[month], 3) == 0) { +			str = skip_space(str + 3); +			break; +		} +	} + +	str = read_num(str, &day, 31); +	str = skip_space(str); + +	t = time(NULL); +	if (localtime_r(&t, tm) == NULL) +		return NULL; + +	year = tm->tm_year; + +	/* sanity check */ +	if (str == NULL || month >= 12 || day < 1) +		return NULL; +	if (month == 11 && tm->tm_mon == 0) +		--year; +	if (day > mdays(year + 1900, month + 1)) +		return NULL; + +	/* decode time */ +	str = read_num(str, &hour, 23); +	if (str == NULL || *(str++) != ':') +		return NULL; +	str = read_num(str, &minute, 59); +	if (str == NULL || *(str++) != ':') +		return NULL; +	str = read_num(str, &second, 59); +	str = skip_space(str); + +	/* store result */ +	memset(tm, 0, sizeof(*tm)); +	tm->tm_sec = second; +	tm->tm_min = minute; +	tm->tm_hour = hour; +	tm->tm_mday = day; +	tm->tm_mon = month; +	tm->tm_year = year; +	return str; +} + +static char *decode_priority(char *str, int *priority) +{ +	while (isspace(*str)) +		++str; +	if (*(str++) != '<') +		return NULL; +	str = read_num(str, priority, 23 * 8 + 7); +	if (str == NULL || *(str++) != '>') +		return NULL; +	while (isspace(*str)) +		++str; +	return str; +} + +int syslog_msg_parse(syslog_msg_t *msg, char *str) +{ +	char *ident, *ptr; +	struct tm tstamp; +	pid_t pid = 0; +	int priority; + +	memset(msg, 0, sizeof(*msg)); + +	str = decode_priority(str, &priority); +	if (str == NULL) +		return -1; + +	msg->facility = priority >> 3; +	msg->level = priority & 0x07; + +	str = read_date_bsd(str, &tstamp); +	if (str == NULL) +		return -1; + +	ident = str; +	while (*str != '\0' && *str != ':') +		++str; + +	if (*str == ':') { +		*(str++) = '\0'; +		while (isspace(*str)) +			++str; + +		ptr = ident; +		while (*ptr != '[' && *ptr != '\0') +			++ptr; + +		if (*ptr == '[') { +			*(ptr++) = '\0'; + +			while (isdigit(*ptr)) +				pid = pid * 10 + *(ptr++) - '0'; +		} +	} else { +		ident = NULL; +	} + +	msg->timestamp = mktime(&tstamp); +	msg->pid = pid; +	msg->ident = ident; +	msg->message = str; +	return 0; +} diff --git a/syslogd/proto.h b/syslogd/proto.h new file mode 100644 index 0000000..c64c9e1 --- /dev/null +++ b/syslogd/proto.h @@ -0,0 +1,35 @@ +/* SPDX-License-Identifier: GPL-3.0-or-later */ +/* + * Copyright (C) 2018 - David Oberhollenzer + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program.  If not, see <https://www.gnu.org/licenses/>. + */ +#ifndef PROTO_H +#define PROTO_H + +#include <sys/types.h> +#include <time.h> + +typedef struct { +	int facility; +	int level; +	time_t timestamp; +	pid_t pid; +	const char *ident; +	const char *message; +} syslog_msg_t; + +int syslog_msg_parse(syslog_msg_t *msg, char *str); + +#endif /* PROTO_H */  | 
