[prev in list] [next in list] [prev in thread] [next in thread]
List: busybox
Subject: Re: syslogd config patch
From: Sergey Naumov <sknaumov () gmail ! com>
Date: 2010-12-30 12:53:00
Message-ID: AANLkTimZyJDCsSAr1yPaw8CGVY4FYX5rzT3UQBxhLMo9 () mail ! gmail ! com
[Download RAW message or body]
Hello.
Denys, here is new version of syslog.conf patch.
I had stable version, but then decided to integrate my patch more
deeply to the existent syslog code, for example - to split logFile_t
struct to logRule_t and logFile_t and to slightly change
ROTATE_LOGFILE feature to support rotation of files that are specified
in syslog.conf.
The next step is to integrate REMOTE_LOG feature too.
Format of syslog.conf:
rule1
rule2
.
.
ruleN
Where:
rule = selector[;selector]* /file/name
selector = facility[,facility]*.[!][=]priority
facility = kern user ... *
priority = emerg ... *
"none" priority is supported
"mark" facility is not suppored
Example:
kern,user.*;kern.!=info;user.!err /var/log/1.log
*.err;user.none;kern.!=debug /dev/console
Any recommendations are welcomed.
Happy New Year,
Sergey Naumov.
["busybox-1.18.1-syslog.conf-v4.0.patch" (application/octet-stream)]
diff -uNr busybox-1.18.1-orig/sysklogd/Config.src busybox-1.18.1/sysklogd/Config.src
--- busybox-1.18.1-orig/sysklogd/Config.src 2010-12-20 03:41:27.000000000 +0300
+++ busybox-1.18.1/sysklogd/Config.src 2010-12-29 15:10:36.000000000 +0300
@@ -52,6 +52,13 @@
Option -D instructs syslogd to drop consecutive messages
which are totally the same.
+config FEATURE_SYSLOGD_CFG
+ bool "Support syslog.conf"
+ default y
+ depends on SYSLOGD
+ help
+ Supports restricted syslogd config.
+
config FEATURE_SYSLOGD_READ_BUFFER_SIZE
int "Read buffer size in bytes"
default 256
diff -uNr busybox-1.18.1-orig/sysklogd/syslogd.c busybox-1.18.1/sysklogd/syslogd.c
--- busybox-1.18.1-orig/sysklogd/syslogd.c 2010-12-20 03:41:27.000000000 +0300
+++ busybox-1.18.1/sysklogd/syslogd.c 2010-12-30 18:07:33.000000000 +0300
@@ -66,10 +66,26 @@
} remoteHost_t;
#endif
+typedef struct logFile_t {
+ const char *path;
+ int fd;
+#if ENABLE_FEATURE_ROTATE_LOGFILE
+ long size;
+ uint8_t isReg;
+#endif
+} logFile_t;
+
+#if ENABLE_FEATURE_SYSLOGD_CFG
+typedef struct logRule_t {
+ uint8_t fpmap[LOG_NFACILITIES];
+ struct logFile_t *file;
+ struct logRule_t *next;
+} logRule_t;
+#endif
+
/* Allows us to have smaller initializer. Ugly. */
#define GLOBALS \
- const char *logFilePath; \
- int logFD; \
+ logFile_t logFile; \
/* interval between marks in seconds */ \
/*int markInterval;*/ \
/* level of messages to be logged */ \
@@ -79,8 +95,6 @@
unsigned logFileSize; \
/* number of rotated message files */ \
unsigned logFileRotate; \
- unsigned curFileSize; \
- smallint isRegular; \
) \
IF_FEATURE_IPC_SYSLOG( \
int shmid; /* ipc shared memory id */ \
@@ -88,6 +102,9 @@
int shm_size; \
struct sembuf SMwup[1]; \
struct sembuf SMwdn[3]; \
+) \
+IF_FEATURE_SYSLOGD_CFG( \
+ logRule_t *pLogR; \
)
struct init_globals {
@@ -119,8 +136,11 @@
};
static const struct init_globals init_data = {
- .logFilePath = "/var/log/messages",
- .logFD = -1,
+ .logFile = {
+ .path = "/var/log/messages",
+ .fd = -1,
+//fields for ENABLE_FEATURE_ROTATE_LOGFILE will be initialized later
+ },
#ifdef SYSLOGD_MARK
.markInterval = 20 * 60,
#endif
@@ -157,6 +177,7 @@
IF_FEATURE_REMOTE_LOG( OPTBIT_locallog ,) // -L
IF_FEATURE_IPC_SYSLOG( OPTBIT_circularlog,) // -C
IF_FEATURE_SYSLOGD_DUP( OPTBIT_dup ,) // -D
+ IF_FEATURE_SYSLOGD_CFG( OPTBIT_cfg ,) // -f
OPT_mark = 1 << OPTBIT_mark ,
OPT_nofork = 1 << OPTBIT_nofork ,
@@ -169,6 +190,7 @@
OPT_locallog = IF_FEATURE_REMOTE_LOG( (1 << OPTBIT_locallog )) + 0,
OPT_circularlog = IF_FEATURE_IPC_SYSLOG( (1 << OPTBIT_circularlog)) + 0,
OPT_dup = IF_FEATURE_SYSLOGD_DUP( (1 << OPTBIT_dup )) + 0,
+ OPT_cfg = IF_FEATURE_SYSLOGD_CFG( (1 << OPTBIT_cfg )) + 0,
};
#define OPTION_STR "m:nO:l:S" \
IF_FEATURE_ROTATE_LOGFILE("s:" ) \
@@ -176,17 +198,186 @@
IF_FEATURE_REMOTE_LOG( "R:" ) \
IF_FEATURE_REMOTE_LOG( "L" ) \
IF_FEATURE_IPC_SYSLOG( "C::") \
- IF_FEATURE_SYSLOGD_DUP( "D" )
+ IF_FEATURE_SYSLOGD_DUP( "D" ) \
+ IF_FEATURE_SYSLOGD_CFG( "f:" )
#define OPTION_DECL *opt_m, *opt_l \
IF_FEATURE_ROTATE_LOGFILE(,*opt_s) \
IF_FEATURE_ROTATE_LOGFILE(,*opt_b) \
- IF_FEATURE_IPC_SYSLOG( ,*opt_C = NULL)
-#define OPTION_PARAM &opt_m, &G.logFilePath, &opt_l \
+ IF_FEATURE_IPC_SYSLOG( ,*opt_C = NULL) \
+ IF_FEATURE_SYSLOGD_CFG(,*opt_f = NULL)
+#define OPTION_PARAM &opt_m, &(G.logFile.path), &opt_l \
IF_FEATURE_ROTATE_LOGFILE(,&opt_s) \
IF_FEATURE_ROTATE_LOGFILE(,&opt_b) \
IF_FEATURE_REMOTE_LOG( ,&remoteAddrList) \
- IF_FEATURE_IPC_SYSLOG( ,&opt_C)
+ IF_FEATURE_IPC_SYSLOG( ,&opt_C) \
+ IF_FEATURE_SYSLOGD_CFG(,&opt_f)
+
+/*
+ * find name by value (then name == NULL) or value by name (then val == -1)
+ * in the set of CODEs and return pointer to appropriate CODE struct.
+ * Ex:
+ * find_fac_prio(LOG_KERN, NULL, facilitynames);
+ * find_fac_prio(LOG_ERR, NULL, prioritynames);
+ * find_fac_prio(-1, "kern", facilitynames);
+ */
+static const CODE* find_fac_prio(int val, char *name, const CODE* c_set)
+{
+ if (!c_set) return NULL;
+ for (; c_set->c_name; c_set++) {
+ if ( (name && strcmp(name, c_set->c_name) == 0)
+ || (c_set->c_val == val) ) {
+ return c_set;
+ }
+ }
+ return NULL;
+}
+
+#if ENABLE_FEATURE_SYSLOGD_CFG
+#define cfgbuf bb_common_bufsiz1
+static void syslogdcfg_parse(const char * file)
+{
+ char *t;
+ char *sel; //pointer to the current selector
+ char *nsel; //pointer to the next selector
+ uint8_t fl_neg; //indicates that selector has negation (kern.!err)
+ uint8_t fl_eq; //indicates that selector has equality (kern.=err)
+ uint32_t facmap; //bitmap of enabled facilities
+ uint8_t primap; //bitmap of enabled priorities
+ uint8_t pri; //priority code
+ uint8_t i; //counter for iteration through facilities/priorities
+ // use double pointer to avoid checking whether head was initialized
+ logRule_t **ppLogR = &(G.pLogR);
+ logRule_t *pLogR;
+ const CODE *code;
+
+ // the first token is selectors set
+ // the second one is file name
+ // the third one have to be NULL
+ char *tok[3];
+ parser_t *parser;
+
+ parser = config_open2(file ? file : "/etc/syslog.conf",
+ file ? xfopen_for_read : fopen_or_warn_stdin);
+ if (!parser)
+ return; //didn't find default /etc/syslog.conf => proceed as if we
+ //built busybox without config support.
+
+ //iterate through lines of config, skipping comments
+ while (config_read(parser, tok, 3, 2,
+ "# \t", PARSE_NORMAL | PARSE_MIN_DIE)) {
+ if (tok[2]) { //unexpected trailing token
+ t = tok[2];
+ goto cfgerr;
+ }
+ *ppLogR = xmalloc(sizeof(logRule_t));
+ pLogR = *ppLogR;
+ memset(pLogR, 0, sizeof(logRule_t));
+ //- first step for each selector in line is to determine
+ //if rule has negation
+ //- second one is to get priority mask.
+ //- third one is to apply this mask to each of listed facility
+ //or to all of them if *
+ sel = tok[0];
+ do { //iterate through selectors
+ nsel = strchr(sel, ';');
+ if (nsel != NULL)
+ *nsel++ = '\0';
+ //process selector
+ fl_neg = 0;
+ fl_eq = 0;
+ facmap = 0;
+ primap = 0;
+ pri = 0;
+ t = strchr(sel, '.');
+ if (t == NULL) {
+ t = sel;
+ goto cfgerr;
+ }
+ *t++ = '\0'; // separate facility from priority
+ if (*t == '!') {
+ fl_neg = 1;
+ ++t;
+ }
+ if (*t == '=') {
+ fl_eq = 1;
+ ++t;
+ }
+ // priority
+ if (*t == '*')
+ primap = 255; //all 8 log levels enabled
+ else {
+ code = find_fac_prio(-1, t, prioritynames);
+ if (code == NULL) goto cfgerr;
+ pri = code->c_val;
+ if (pri == INTERNAL_NOPRI) {
+ primap = 0;
+ fl_neg = 1; //so fpmap[fac] &= 0
+ } else {
+ primap = (1<<pri);
+ if (!fl_eq) {
+ for (i = 0; i < pri; ++i) primap |= (1<<i);
+ }
+ if (fl_neg)
+ primap = ~primap;
+ }
+ }
+ //facility
+ if (*sel == '*')
+ facmap = (1<<LOG_NFACILITIES) - 1;
+ else {
+ char * nfac;
+ t = sel;
+ do { //iterate through facilities
+ nfac = strchr(t, ',');
+ if (nfac != NULL)
+ *nfac++ = '\0';
+ code = find_fac_prio(-1, t, facilitynames);
+ if (code == NULL)
+ goto cfgerr;
+ if (code->c_val != INTERNAL_MARK) { //discard mark
+ facmap |= 1<<(LOG_FAC(code->c_val));
+ }
+ t = nfac;
+ } while (t != NULL);
+ }
+ //merge result with previous selectors
+ for (i = 0; i < LOG_NFACILITIES; ++i) {
+ if ((facmap & (1<<i)) == 0)
+ continue;
+ if (fl_neg)
+ pLogR->fpmap[i] &= primap;
+ else
+ pLogR->fpmap[i] |= primap;
+ }
+ //process next selector
+ sel = nsel;
+ } while (sel != NULL);
+ //temporarily use pLogR as iterator, but *ppLogR still points to
+ //currently processing rule entry.
+ //check whether current file name was mentioned in previous rules.
+ //NOTE: *ppLogR points to the current (and last in the list) rule.
+ for (pLogR = G.pLogR; pLogR != *ppLogR; pLogR = pLogR->next) {
+ if (strcmp(pLogR->file->path, tok[1]) == 0) {
+ (*ppLogR)->file = pLogR->file;
+ break;
+ }
+ }
+ if (pLogR == *ppLogR) { //new file
+ pLogR->file = xmalloc(sizeof(logFile_t));
+ pLogR->file->fd = -1;
+ pLogR->file->path = xstrdup(tok[1]);
+ //fields for ENABLE_FEATURE_ROTATE_LOGFILE will be initialized later
+ }
+ ppLogR = &((*ppLogR)->next);
+ }
+ config_close(parser);
+ return;
+cfgerr:
+ bb_error_msg_and_die("bad line %d: wrong token \"%s\".",
+ parser->lineno, t);
+}
+#endif
/* circular buffer variables/structures */
#if ENABLE_FEATURE_IPC_SYSLOG
@@ -288,9 +479,8 @@
void log_to_shmem(const char *msg);
#endif /* FEATURE_IPC_SYSLOG */
-
/* Print a message to the log file. */
-static void log_locally(time_t now, char *msg)
+static void log_locally(time_t now, char *msg, logFile_t *logF)
{
#ifdef SYSLOGD_WRLOCK
struct flock fl;
@@ -303,7 +493,7 @@
return;
}
#endif
- if (G.logFD >= 0) {
+ if (logF->fd >= 0) {
/* Reopen log file every second. This allows admin
* to delete the file and not worry about restarting us.
* This costs almost nothing since it happens
@@ -313,15 +503,15 @@
now = time(NULL);
if (G.last_log_time != now) {
G.last_log_time = now;
- close(G.logFD);
+ close(logF->fd);
goto reopen;
}
} else {
reopen:
- G.logFD = open(G.logFilePath, O_WRONLY | O_CREAT
+ logF->fd = open(logF->path, O_WRONLY | O_CREAT
| O_NOCTTY | O_APPEND | O_NONBLOCK,
0666);
- if (G.logFD < 0) {
+ if (logF->fd < 0) {
/* cannot open logfile? - print to /dev/console then */
int fd = device_open(DEV_CONSOLE, O_WRONLY | O_NOCTTY | O_NONBLOCK);
if (fd < 0)
@@ -334,9 +524,10 @@
#if ENABLE_FEATURE_ROTATE_LOGFILE
{
struct stat statf;
- G.isRegular = (fstat(G.logFD, &statf) == 0 && S_ISREG(statf.st_mode));
+ logF->isReg =
+ (fstat(logF->fd, &statf) == 0 && S_ISREG(statf.st_mode));
/* bug (mostly harmless): can wrap around if file > 4gb */
- G.curFileSize = statf.st_size;
+ logF->size = statf.st_size;
}
#endif
}
@@ -346,41 +537,41 @@
fl.l_start = 0;
fl.l_len = 1;
fl.l_type = F_WRLCK;
- fcntl(G.logFD, F_SETLKW, &fl);
+ fcntl(logF->fd, F_SETLKW, &fl);
#endif
#if ENABLE_FEATURE_ROTATE_LOGFILE
- if (G.logFileSize && G.isRegular && G.curFileSize > G.logFileSize) {
+ if (G.logFileSize && logF->isReg && logF->size > G.logFileSize) {
if (G.logFileRotate) { /* always 0..99 */
- int i = strlen(G.logFilePath) + 3 + 1;
+ int i = strlen(logF->path) + 3 + 1;
char oldFile[i];
char newFile[i];
i = G.logFileRotate - 1;
/* rename: f.8 -> f.9; f.7 -> f.8; ... */
while (1) {
- sprintf(newFile, "%s.%d", G.logFilePath, i);
+ sprintf(newFile, "%s.%d", logF->path, i);
if (i == 0) break;
- sprintf(oldFile, "%s.%d", G.logFilePath, --i);
+ sprintf(oldFile, "%s.%d", logF->path, --i);
/* ignore errors - file might be missing */
rename(oldFile, newFile);
}
/* newFile == "f.0" now */
- rename(G.logFilePath, newFile);
+ rename(logF->path, newFile);
#ifdef SYSLOGD_WRLOCK
fl.l_type = F_UNLCK;
- fcntl(G.logFD, F_SETLKW, &fl);
+ fcntl(logF->fd, F_SETLKW, &fl);
#endif
- close(G.logFD);
+ close(logF->fd);
goto reopen;
}
- ftruncate(G.logFD, 0);
+ ftruncate(logF->fd, 0);
}
- G.curFileSize +=
+ logF->size +=
#endif
- full_write(G.logFD, msg, len);
+ full_write(logF->fd, msg, len);
#ifdef SYSLOGD_WRLOCK
fl.l_type = F_UNLCK;
- fcntl(G.logFD, F_SETLKW, &fl);
+ fcntl(logF->fd, F_SETLKW, &fl);
#endif
}
@@ -389,27 +580,13 @@
const CODE *c_pri, *c_fac;
if (pri != 0) {
- c_fac = facilitynames;
- while (c_fac->c_name) {
- if (c_fac->c_val != (LOG_FAC(pri) << 3)) {
- c_fac++;
- continue;
- }
- /* facility is found, look for prio */
- c_pri = prioritynames;
- while (c_pri->c_name) {
- if (c_pri->c_val != LOG_PRI(pri)) {
- c_pri++;
- continue;
- }
- snprintf(res20, 20, "%s.%s",
- c_fac->c_name, c_pri->c_name);
- return;
- }
- /* prio not found, bail out */
- break;
+ c_fac = find_fac_prio(LOG_FAC(pri) << 3, NULL, facilitynames);
+ c_pri = find_fac_prio(LOG_PRI(pri), NULL, prioritynames);
+ if (c_fac && c_pri) {
+ snprintf(res20, 20, "%s.%s", c_fac->c_name, c_pri->c_name);
+ } else {
+ snprintf(res20, 20, "<%d>", pri);
}
- snprintf(res20, 20, "<%d>", pri);
}
}
@@ -444,7 +621,26 @@
}
/* Log message locally (to file or shared mem) */
- log_locally(now, G.printbuf);
+#if ENABLE_FEATURE_SYSLOGD_CFG
+ {
+ uint8_t match = 0;
+ logRule_t *pLogR;
+ uint8_t mfac = LOG_FAC(pri);
+ uint8_t mpri = LOG_PRI(pri);
+
+ for (pLogR = G.pLogR; pLogR != NULL; pLogR = pLogR->next)
+ {
+ if ((pLogR->fpmap[mfac] & (1<<mpri))) {
+ log_locally(now, G.printbuf, pLogR->file);
+ match = 1;
+ }
+ }
+ if (match) return;
+ }
+#endif
+ if (LOG_PRI(pri) < G.logLevel) { //moved from split_escape_and_log
+ log_locally(now, G.printbuf, &(G.logFile));
+ }
}
static void timestamp_and_log_internal(const char *msg)
@@ -489,8 +685,8 @@
*q = '\0';
/* Now log it */
- if (LOG_PRI(pri) < G.logLevel)
- timestamp_and_log(pri, G.parsebuf, q - G.parsebuf);
+// if (LOG_PRI(pri) < G.logLevel) //moved inside timestamp_and_log()
+ timestamp_and_log(pri, G.parsebuf, q - G.parsebuf);
}
}
@@ -715,6 +911,10 @@
G.shm_size = xatoul_range(opt_C, 4, INT_MAX/1024) * 1024;
#endif
+#if ENABLE_FEATURE_SYSLOGD_CFG
+ syslogdcfg_parse(opt_f);
+#endif
+
/* If they have not specified remote logging, then log locally */
if (ENABLE_FEATURE_REMOTE_LOG && !(opts & OPT_remotelog)) // -R
option_mask32 |= OPT_locallog;
_______________________________________________
busybox mailing list
busybox@busybox.net
http://lists.busybox.net/mailman/listinfo/busybox
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic