3ad5b60452
- fix #666677 - preserve ACLs when rotating files
2025 lines
54 KiB
Diff
2025 lines
54 KiB
Diff
Index: config.c
|
|
===================================================================
|
|
--- config.c (revision 290)
|
|
+++ config.c (working copy)
|
|
@@ -1,5 +1,9 @@
|
|
#include <sys/queue.h>
|
|
+#ifdef _ALLOCA_H
|
|
#include <alloca.h>
|
|
+#else
|
|
+#include <limits.h>
|
|
+#endif
|
|
#include <ctype.h>
|
|
#include <dirent.h>
|
|
#include <errno.h>
|
|
@@ -30,13 +34,55 @@
|
|
|
|
#define REALLOC_STEP 10
|
|
|
|
-#if defined(SunOS)
|
|
-#include <syslimits.h>
|
|
+#if defined(SunOS)
|
|
+#include <limits.h>
|
|
#if !defined(isblank)
|
|
#define isblank(c) ( (c) == ' ' || (c) == '\t' ) ? 1 : 0
|
|
#endif
|
|
#endif
|
|
|
|
+#if !defined(asprintf)
|
|
+#include <stdarg.h>
|
|
+
|
|
+int asprintf(char **string_ptr, const char *format, ...)
|
|
+{
|
|
+ va_list arg;
|
|
+ char *str;
|
|
+ int size;
|
|
+ int rv;
|
|
+
|
|
+ va_start(arg, format);
|
|
+ size = vsnprintf(NULL, 0, format, arg);
|
|
+ size++;
|
|
+ va_start(arg, format);
|
|
+ str = malloc(size);
|
|
+ if (str == NULL) {
|
|
+ va_end(arg);
|
|
+ /*
|
|
+ * Strictly speaking, GNU asprintf doesn't do this,
|
|
+ * but the caller isn't checking the return value.
|
|
+ */
|
|
+ fprintf(stderr, "failed to allocate memory\\n");
|
|
+ exit(1);
|
|
+ }
|
|
+ rv = vsnprintf(str, size, format, arg);
|
|
+ va_end(arg);
|
|
+
|
|
+ *string_ptr = str;
|
|
+ return (rv);
|
|
+}
|
|
+
|
|
+#endif
|
|
+
|
|
+enum {
|
|
+ STATE_DEFAULT = 2,
|
|
+ STATE_SKIP_LINE = 4,
|
|
+ STATE_DEFINITION_END = 8,
|
|
+ STATE_SKIP_CONFIG = 16,
|
|
+ STATE_LOAD_SCRIPT = 32,
|
|
+ STATE_ERROR = 64,
|
|
+};
|
|
+
|
|
static char *defTabooExts[] = { ".rpmsave", ".rpmorig", "~", ",v",
|
|
".disabled", ".dpkg-old", ".dpkg-dist", ".dpkg-new", ".cfsaved",
|
|
".ucf-old", ".ucf-dist", ".ucf-new",
|
|
@@ -52,51 +98,71 @@
|
|
static int readConfigFile(const char *configFile, struct logInfo *defConfig);
|
|
static int globerr(const char *pathname, int theerr);
|
|
|
|
-static int isolateValue(const char *fileName, int lineNum, char *key,
|
|
- char **startPtr, char **endPtr)
|
|
+static char *isolateLine(char **strt, char **buf, size_t length) {
|
|
+ char *endtag, *start, *tmp;
|
|
+ start = *strt;
|
|
+ endtag = start;
|
|
+ while (endtag - *buf < length && *endtag != '\n') {
|
|
+ endtag++;}
|
|
+ if (endtag - *buf > length)
|
|
+ return NULL;
|
|
+ tmp = endtag - 1;
|
|
+ while (isspace(*endtag))
|
|
+ endtag--;
|
|
+ char *key = strndup(start, endtag - start + 1);
|
|
+ *strt = tmp;
|
|
+ return key;
|
|
+}
|
|
+
|
|
+static char *isolateValue(const char *fileName, int lineNum, char *key,
|
|
+ char **startPtr, char **buf, size_t length)
|
|
{
|
|
char *chptr = *startPtr;
|
|
|
|
- while (isblank(*chptr))
|
|
+ while (chptr - *buf < length && isblank(*chptr))
|
|
chptr++;
|
|
- if (*chptr == '=') {
|
|
+ if (chptr - *buf < length && *chptr == '=') {
|
|
chptr++;
|
|
- while (*chptr && isblank(*chptr))
|
|
+ while ( chptr - *buf < length && isblank(*chptr))
|
|
chptr++;
|
|
}
|
|
|
|
- if (*chptr == '\n') {
|
|
- message(MESS_ERROR, "%s:%d argument expected after %s\n",
|
|
- fileName, lineNum, key);
|
|
- return 1;
|
|
+ if (chptr - *buf < length && *chptr == '\n') {
|
|
+ message(MESS_ERROR, "%s:%d argument expected after %s\n",
|
|
+ fileName, lineNum, key);
|
|
+ return NULL;
|
|
}
|
|
|
|
- *startPtr = chptr;
|
|
+ *startPtr = chptr;
|
|
+ return isolateLine(startPtr, buf, length);
|
|
+}
|
|
|
|
- while (*chptr != '\n')
|
|
- chptr++;
|
|
-
|
|
- while (isspace(*chptr))
|
|
- chptr--;
|
|
-
|
|
- *endPtr = chptr + 1;
|
|
-
|
|
- return 0;
|
|
+static char *isolateWord(char **strt, char **buf, size_t length) {
|
|
+ char *endtag, *start;
|
|
+ start = *strt;
|
|
+ while (start - *buf < length && isblank(*start))
|
|
+ start++;
|
|
+ endtag = start;
|
|
+ while (endtag - *buf < length && isalpha(*endtag)) {
|
|
+ endtag++;}
|
|
+ if (endtag - *buf > length)
|
|
+ return NULL;
|
|
+ char *key = strndup(start, endtag - start);
|
|
+ *strt = endtag;
|
|
+ return key;
|
|
}
|
|
|
|
static char *readPath(const char *configFile, int lineNum, char *key,
|
|
- char **startPtr)
|
|
+ char **startPtr, char **buf, size_t length)
|
|
{
|
|
- char oldchar;
|
|
- char *endtag, *chptr;
|
|
+ char *chptr;
|
|
char *start = *startPtr;
|
|
char *path;
|
|
|
|
wchar_t pwc;
|
|
size_t len;
|
|
|
|
- if (!isolateValue(configFile, lineNum, key, &start, &endtag)) {
|
|
- oldchar = *endtag, *endtag = '\0';
|
|
+ if ((start = isolateValue(configFile, lineNum, key, startPtr, buf, length)) != NULL) {
|
|
|
|
chptr = start;
|
|
|
|
@@ -120,29 +186,23 @@
|
|
*/
|
|
|
|
path = strdup(start);
|
|
+ free(start);
|
|
|
|
-
|
|
- *endtag = oldchar, start = endtag;
|
|
-
|
|
- *startPtr = start;
|
|
-
|
|
return path;
|
|
} else
|
|
return NULL;
|
|
}
|
|
|
|
static char *readAddress(const char *configFile, int lineNum, char *key,
|
|
- char **startPtr)
|
|
+ char **startPtr, char **buf, size_t length)
|
|
{
|
|
- char oldchar;
|
|
char *endtag, *chptr;
|
|
char *start = *startPtr;
|
|
char *address;
|
|
|
|
- if (!isolateValue(configFile, lineNum, key, &start, &endtag)) {
|
|
- oldchar = *endtag, *endtag = '\0';
|
|
+ if ((endtag = isolateValue(configFile, lineNum, key, startPtr, buf, length)) != NULL) {
|
|
|
|
- chptr = start;
|
|
+ chptr = endtag;
|
|
while (*chptr && isprint(*chptr) && *chptr != ' ')
|
|
chptr++;
|
|
if (*chptr) {
|
|
@@ -151,12 +211,9 @@
|
|
return NULL;
|
|
}
|
|
|
|
- address = strdup(start);
|
|
+ address = strdup(chptr);
|
|
+ free(endtag);
|
|
|
|
- *endtag = oldchar, start = endtag;
|
|
-
|
|
- *startPtr = start;
|
|
-
|
|
return address;
|
|
} else
|
|
return NULL;
|
|
@@ -484,8 +541,8 @@
|
|
static int readConfigFile(const char *configFile, struct logInfo *defConfig)
|
|
{
|
|
int fd;
|
|
- char *buf, *endtag;
|
|
- char oldchar, foo;
|
|
+ char *buf, *endtag, *key = NULL;
|
|
+ char foo;
|
|
off_t length;
|
|
int lineNum = 1;
|
|
int multiplier;
|
|
@@ -504,6 +561,8 @@
|
|
glob_t globResult;
|
|
const char **argv;
|
|
int argc, argNum;
|
|
+ int flags;
|
|
+ int state = STATE_DEFAULT;
|
|
int logerror = 0;
|
|
struct logInfo *log;
|
|
static unsigned recursion_depth = 0U;
|
|
@@ -519,17 +578,28 @@
|
|
length arrays -- of course, if we aren't run setuid it doesn't
|
|
matter much */
|
|
|
|
- fd = open(configFile, O_RDONLY | O_CLOEXEC);
|
|
- if (fd < 0) {
|
|
- message(MESS_ERROR, "failed to open config file %s: %s\n",
|
|
- configFile, strerror(errno));
|
|
- return 1;
|
|
- }
|
|
+ fd = open(configFile, O_RDONLY);
|
|
+ if (fd < 0) {
|
|
+ message(MESS_ERROR, "failed to open config file %s: %s\n",
|
|
+ configFile, strerror(errno));
|
|
+ return 1;
|
|
+ }
|
|
+ if ((flags = fcntl(fd, F_GETFD)) == -1) {
|
|
+ message(MESS_ERROR, "Could not retrieve flags from file %s\n",
|
|
+ configFile);
|
|
+ return 1;
|
|
+ }
|
|
+ flags |= FD_CLOEXEC;
|
|
+ if (fcntl(fd, F_SETFD, flags) == -1) {
|
|
+ message(MESS_ERROR, "Could not set flags on file %s\n",
|
|
+ configFile);
|
|
+ return 1;
|
|
+ }
|
|
/* We don't want anybody to change the file while we parse it,
|
|
* let's try to lock it for reading. */
|
|
if (fcntl(fd, F_SETLK, &fd_lock) == -1) {
|
|
- message(MESS_ERROR, "Could not lock file %s for reading\n",
|
|
- configFile);
|
|
+ message(MESS_ERROR, "Could not lock file %s for reading\n",
|
|
+ configFile);
|
|
}
|
|
if (fstat(fd, &sb)) {
|
|
message(MESS_ERROR, "fstat of %s failed: %s\n", configFile,
|
|
@@ -546,8 +616,24 @@
|
|
}
|
|
|
|
length = sb.st_size;
|
|
- buf = mmap(NULL, (size_t)(length + 2), PROT_READ | PROT_WRITE,
|
|
- MAP_PRIVATE | MAP_POPULATE, fd, (off_t) 0);
|
|
+
|
|
+ /* We can't mmap empty file... */
|
|
+ if (length == 0) {
|
|
+ message(MESS_DEBUG,
|
|
+ "Ignoring %s because it's empty.\n",
|
|
+ configFile);
|
|
+ close(fd);
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+#ifdef MAP_POPULATE
|
|
+ buf = mmap(NULL, (size_t) length, PROT_READ,
|
|
+ MAP_PRIVATE | MAP_POPULATE, fd, (off_t) 0);
|
|
+#else /* MAP_POPULATE */
|
|
+ buf = mmap(NULL, (size_t) length, PROT_READ,
|
|
+ MAP_PRIVATE, fd, (off_t) 0);
|
|
+#endif /* MAP_POPULATE */
|
|
+
|
|
if (buf == MAP_FAILED) {
|
|
message(MESS_ERROR, "Error mapping config file %s: %s\n",
|
|
configFile, strerror(errno));
|
|
@@ -555,964 +641,812 @@
|
|
return 1;
|
|
}
|
|
|
|
- /* knowing the buffer ends with a newline makes things (a bit) cleaner */
|
|
- buf[length + 1] = '\0';
|
|
- buf[length] = '\n';
|
|
+#ifdef MADV_DONTFORK
|
|
madvise(buf, (size_t)(length + 2),
|
|
MADV_SEQUENTIAL | MADV_WILLNEED | MADV_DONTFORK);
|
|
+#else /* MADV_DONTFORK */
|
|
+ madvise(buf, (size_t)(length + 2),
|
|
+ MADV_SEQUENTIAL | MADV_WILLNEED);
|
|
+#endif /* MADV_DONTFORK */
|
|
|
|
message(MESS_DEBUG, "reading config file %s\n", configFile);
|
|
|
|
- start = buf;
|
|
- while (*start) {
|
|
- if (logerror) {
|
|
- assert(newlog != defConfig);
|
|
-
|
|
- message(MESS_ERROR, "found error in %s, skipping\n",
|
|
- newlog->pattern ? newlog->pattern : "log config");
|
|
-
|
|
- while (*start != '}') {
|
|
- if (*start == 0) {
|
|
- message(MESS_ERROR, "%s:%d } expected \n",
|
|
- configFile, lineNum);
|
|
- goto error;
|
|
- } else if (*start == '\n') {
|
|
- while (isspace(*start) && (*start)) {
|
|
- if (*start == '\n')
|
|
- lineNum++;
|
|
- start++;
|
|
- }
|
|
- } else if (
|
|
- (strncmp(start, "postrotate", 10) == 0) ||
|
|
- (strncmp(start, "prerotate", 9) == 0) ||
|
|
- (strncmp(start, "firstrotate", 11) == 0) ||
|
|
- (strncmp(start, "lastrotate", 10) == 0)
|
|
- )
|
|
- {
|
|
- while (*start) {
|
|
- while ((*start != '\n') && (*start))
|
|
- start++;
|
|
- while (isspace(*start) && (*start)) {
|
|
- if (*start == '\n')
|
|
- lineNum++;
|
|
- start++;
|
|
+ start = buf;
|
|
+ for (start = buf; start - buf < length; start++) {
|
|
+ if (key) {
|
|
+ free(key);
|
|
+ key = NULL;
|
|
+ }
|
|
+ switch (state) {
|
|
+ case STATE_DEFAULT:
|
|
+ if (isblank(*start))
|
|
+ continue;
|
|
+ /* Skip comment */
|
|
+ if (*start == '#') {
|
|
+ state = STATE_SKIP_LINE;
|
|
+ continue;
|
|
}
|
|
- if (strncmp(start, "endscript", 9) == 0) {
|
|
- start += 9;
|
|
- break;
|
|
- }
|
|
- }
|
|
- } else {
|
|
- start++;
|
|
- }
|
|
- }
|
|
- start++;
|
|
+
|
|
+ if (isalpha(*start)) {
|
|
+ if ((key = isolateWord(&start, &buf, length)) == NULL)
|
|
+ continue;
|
|
+ if (!strcmp(key, "compress")) {
|
|
+ newlog->flags |= LOG_FLAG_COMPRESS;
|
|
+ } else if (!strcmp(key, "nocompress")) {
|
|
+ newlog->flags &= ~LOG_FLAG_COMPRESS;
|
|
+ } else if (!strcmp(key, "compress")) {
|
|
+ newlog->flags |= LOG_FLAG_COMPRESS;
|
|
+ } else if (!strcmp(key, "nocompress")) {
|
|
+ newlog->flags &= ~LOG_FLAG_COMPRESS;
|
|
+ } else if (!strcmp(key, "delaycompress")) {
|
|
+ newlog->flags |= LOG_FLAG_DELAYCOMPRESS;
|
|
+ } else if (!strcmp(key, "nodelaycompress")) {
|
|
+ newlog->flags &= ~LOG_FLAG_DELAYCOMPRESS;
|
|
+ } else if (!strcmp(key, "shred")) {
|
|
+ newlog->flags |= LOG_FLAG_SHRED;
|
|
+ } else if (!strcmp(key, "noshred")) {
|
|
+ newlog->flags &= ~LOG_FLAG_SHRED;
|
|
+ } else if (!strcmp(key, "sharedscripts")) {
|
|
+ newlog->flags |= LOG_FLAG_SHAREDSCRIPTS;
|
|
+ } else if (!strcmp(key, "nosharedscripts")) {
|
|
+ newlog->flags &= ~LOG_FLAG_SHAREDSCRIPTS;
|
|
+ } else if (!strcmp(key, "copytruncate")) {
|
|
+ newlog->flags |= LOG_FLAG_COPYTRUNCATE;
|
|
+ } else if (!strcmp(key, "nocopytruncate")) {
|
|
+ newlog->flags &= ~LOG_FLAG_COPYTRUNCATE;
|
|
+ } else if (!strcmp(key, "copy")) {
|
|
+ newlog->flags |= LOG_FLAG_COPY;
|
|
+ } else if (!strcmp(key, "nocopy")) {
|
|
+ newlog->flags &= ~LOG_FLAG_COPY;
|
|
+ } else if (!strcmp(key, "ifempty")) {
|
|
+ newlog->flags |= LOG_FLAG_IFEMPTY;
|
|
+ } else if (!strcmp(key, "notifempty")) {
|
|
+ newlog->flags &= ~LOG_FLAG_IFEMPTY;
|
|
+ } else if (!strcmp(key, "dateext")) {
|
|
+ newlog->flags |= LOG_FLAG_DATEEXT;
|
|
+ } else if (!strcmp(key, "nodateext")) {
|
|
+ newlog->flags &= ~LOG_FLAG_DATEEXT;
|
|
+ } else if (!strcmp(key, "dateformat")) {
|
|
+ freeLogItem(dateformat);
|
|
+ newlog->dateformat = isolateLine(&start, &buf, length);
|
|
+ if (newlog->dateformat == NULL)
|
|
+ continue;
|
|
+ } else if (!strcmp(key, "noolddir")) {
|
|
+ newlog->oldDir = NULL;
|
|
+ } else if (!strcmp(key, "mailfirst")) {
|
|
+ newlog->flags |= LOG_FLAG_MAILFIRST;
|
|
+ } else if (!strcmp(key, "maillast")) {
|
|
+ newlog->flags &= ~LOG_FLAG_MAILFIRST;
|
|
+ } else if (!strcmp(key, "create")) {
|
|
+ free(key);
|
|
+ key = isolateLine(&start, &buf, length);
|
|
+ if (key == NULL)
|
|
+ continue;
|
|
|
|
- freeTailLogs(1);
|
|
- newlog = defConfig;
|
|
- logerror = 0;
|
|
- }
|
|
- while (isblank(*start) && (*start))
|
|
- start++;
|
|
- if (*start == '#') {
|
|
- while (*start != '\n')
|
|
- start++;
|
|
- }
|
|
+ rc = sscanf(key, "%o %s %s%c", &createMode,
|
|
+ createOwner, createGroup, &foo);
|
|
+ if (rc == 4) {
|
|
+ message(MESS_ERROR, "%s:%d extra arguments for "
|
|
+ "create\n", configFile, lineNum);
|
|
+ if (newlog != defConfig) {
|
|
+ state = STATE_ERROR;
|
|
+ continue;
|
|
+ } else {
|
|
+ goto error;
|
|
+ }
|
|
+ }
|
|
|
|
- if (*start == '\n') {
|
|
- start++;
|
|
- lineNum++;
|
|
- continue;
|
|
- }
|
|
+ if (rc > 0)
|
|
+ newlog->createMode = createMode;
|
|
|
|
- if (scriptStart) {
|
|
- if (!strncmp(start, "endscript", 9)) {
|
|
- chptr = start + 9;
|
|
- while (isblank(*chptr))
|
|
- chptr++;
|
|
- if (*chptr == '\n') {
|
|
- endtag = start;
|
|
- while (*endtag != '\n')
|
|
- endtag--;
|
|
- endtag++;
|
|
- *scriptDest = malloc(endtag - scriptStart + 1);
|
|
- strncpy(*scriptDest, scriptStart,
|
|
- endtag - scriptStart);
|
|
- (*scriptDest)[endtag - scriptStart] = '\0';
|
|
- start = chptr + 1;
|
|
- lineNum++;
|
|
+ if (rc > 1) {
|
|
+ pw = getpwnam(createOwner);
|
|
+ if (!pw) {
|
|
+ message(MESS_ERROR, "%s:%d unknown user '%s'\n",
|
|
+ configFile, lineNum, createOwner);
|
|
+ if (newlog != defConfig) {
|
|
+ state = STATE_ERROR;
|
|
+ continue;
|
|
+ } else {
|
|
+ goto error;
|
|
+ }
|
|
+ }
|
|
+ newlog->createUid = pw->pw_uid;
|
|
+ endpwent();
|
|
+ }
|
|
+ if (rc > 2) {
|
|
+ group = getgrnam(createGroup);
|
|
+ if (!group) {
|
|
+ message(MESS_ERROR, "%s:%d unknown group '%s'\n",
|
|
+ configFile, lineNum, createGroup);
|
|
+ if (newlog != defConfig) {
|
|
+ state = STATE_ERROR;
|
|
+ continue;
|
|
+ } else {
|
|
+ goto error;
|
|
+ }
|
|
+ }
|
|
+ newlog->createGid = group->gr_gid;
|
|
+ endgrent();
|
|
+ }
|
|
|
|
- scriptDest = NULL;
|
|
- scriptStart = NULL;
|
|
- }
|
|
- }
|
|
+ newlog->flags |= LOG_FLAG_CREATE;
|
|
+ } else if (!strcmp(key, "nocreate")) {
|
|
+ newlog->flags &= ~LOG_FLAG_CREATE;
|
|
+ } else if (!strcmp(key, "size") || !strcmp(key, "minsize")) {
|
|
+ unsigned long long size = 0;
|
|
+ char *opt = key;
|
|
+
|
|
+ if ((key = isolateValue(configFile, lineNum, opt, &start,
|
|
+ &buf, length)) != NULL) {
|
|
+ free(opt);
|
|
+ int l = strlen(key) - 1;
|
|
+ if (key[l] == 'k') {
|
|
+ key[l] = '\0';
|
|
+ multiplier = 1024;
|
|
+ } else if (key[l] == 'M') {
|
|
+ key[l] = '\0';
|
|
+ multiplier = 1024 * 1024;
|
|
+ } else if (key[l] == 'G') {
|
|
+ key[l] = '\0';
|
|
+ multiplier = 1024 * 1024 * 1024;
|
|
+ } else if (!isdigit(key[l])) {
|
|
+ message(MESS_ERROR, "%s:%d unknown unit '%c'\n",
|
|
+ configFile, lineNum, key[l]);
|
|
+ if (newlog != defConfig) {
|
|
+ state = STATE_ERROR;
|
|
+ continue;
|
|
+ } else {
|
|
+ goto error;
|
|
+ }
|
|
+ } else {
|
|
+ multiplier = 1;
|
|
+ }
|
|
|
|
- if (scriptStart) {
|
|
- while (*start != '\n')
|
|
- start++;
|
|
- lineNum++;
|
|
- start++;
|
|
- }
|
|
- } else if (isalpha(*start)) {
|
|
- endtag = start;
|
|
- while (isalpha(*endtag))
|
|
- endtag++;
|
|
- oldchar = *endtag;
|
|
- *endtag = '\0';
|
|
+ size = multiplier * strtoul(key, &chptr, 0);
|
|
+ if (*chptr) {
|
|
+ message(MESS_ERROR, "%s:%d bad size '%s'\n",
|
|
+ configFile, lineNum, key);
|
|
+ if (newlog != defConfig) {
|
|
+ state = STATE_ERROR;
|
|
+ continue;
|
|
+ } else {
|
|
+ goto error;
|
|
+ }
|
|
+ }
|
|
+ if (!strncmp(key, "size", 4)) {
|
|
+ newlog->criterium = ROT_SIZE;
|
|
+ newlog->threshhold = size;
|
|
+ } else
|
|
+ newlog->minsize = size;
|
|
+ }
|
|
+ else {
|
|
+ free(opt);
|
|
+ continue;
|
|
+ }
|
|
+ } else if (!strcmp(key, "shredcycles")) {
|
|
+ free(key);
|
|
+ if ((key = isolateValue(configFile, lineNum, "shred cycles",
|
|
+ &start, &buf, length)) != NULL) {
|
|
+ newlog->shred_cycles = strtoul(key, &chptr, 0);
|
|
+ if (*chptr || newlog->shred_cycles < 0) {
|
|
+ message(MESS_ERROR, "%s:%d bad shred cycles '%s'\n",
|
|
+ configFile, lineNum, key);
|
|
+ goto error;
|
|
+ }
|
|
+ }
|
|
+ else continue;
|
|
+ } else if (!strcmp(key, "daily")) {
|
|
+ newlog->criterium = ROT_DAYS;
|
|
+ newlog->threshhold = 1;
|
|
+ } else if (!strcmp(key, "monthly")) {
|
|
+ newlog->criterium = ROT_MONTHLY;
|
|
+ } else if (!strcmp(key, "weekly")) {
|
|
+ newlog->criterium = ROT_WEEKLY;
|
|
+ } else if (!strcmp(key, "yearly")) {
|
|
+ newlog->criterium = ROT_YEARLY;
|
|
+ } else if (!strcmp(key, "rotate")) {
|
|
+ free(key);
|
|
+ if ((key = isolateValue
|
|
+ (configFile, lineNum, "rotate count", &start,
|
|
+ &buf, length)) != NULL) {
|
|
|
|
- if (!strcmp(start, "compress")) {
|
|
- newlog->flags |= LOG_FLAG_COMPRESS;
|
|
+ newlog->rotateCount = strtoul(key, &chptr, 0);
|
|
+ if (*chptr || newlog->rotateCount < 0) {
|
|
+ message(MESS_ERROR,
|
|
+ "%s:%d bad rotation count '%s'\n",
|
|
+ configFile, lineNum, key);
|
|
+ if (newlog != defConfig) {
|
|
+ state = STATE_ERROR;
|
|
+ continue;
|
|
+ } else {
|
|
+ goto error;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ else continue;
|
|
+ } else if (!strcmp(key, "start")) {
|
|
+ free(key);
|
|
+ if ((key = isolateValue
|
|
+ (configFile, lineNum, "start count", &start,
|
|
+ &buf, length)) != NULL) {
|
|
|
|
- *endtag = oldchar, start = endtag;
|
|
- } else if (!strcmp(start, "nocompress")) {
|
|
- newlog->flags &= ~LOG_FLAG_COMPRESS;
|
|
+ newlog->logStart = strtoul(start, &chptr, 0);
|
|
+ if (*chptr || newlog->logStart < 0) {
|
|
+ message(MESS_ERROR, "%s:%d bad start count '%s'\n",
|
|
+ configFile, lineNum, key);
|
|
+ if (newlog != defConfig) {
|
|
+ state = STATE_ERROR;
|
|
+ continue;
|
|
+ } else {
|
|
+ goto error;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ else continue;
|
|
+ } else if (!strcmp(key, "maxage")) {
|
|
+ free(key);
|
|
+ if ((key = isolateValue
|
|
+ (configFile, lineNum, "maxage count", &start,
|
|
+ &buf, length)) != NULL) {
|
|
+ newlog->rotateAge = strtoul(start, &chptr, 0);
|
|
+ if (*chptr || newlog->rotateAge < 0) {
|
|
+ message(MESS_ERROR, "%s:%d bad maximum age '%s'\n",
|
|
+ configFile, lineNum, start);
|
|
+ if (newlog != defConfig) {
|
|
+ state = STATE_ERROR;
|
|
+ continue;
|
|
+ } else {
|
|
+ goto error;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ else continue;
|
|
+ } else if (!strcmp(key, "errors")) {
|
|
+ message(MESS_DEBUG,
|
|
+ "%s: %d: the errors directive is deprecated and no longer used.\n",
|
|
+ configFile, lineNum);
|
|
+ } else if (!strcmp(key, "mail")) {
|
|
+ freeLogItem(logAddress);
|
|
+ if (!(newlog->logAddress = readAddress(configFile, lineNum,
|
|
+ "mail", &start, &buf, length))) {
|
|
+ if (newlog != defConfig) {
|
|
+ state = STATE_ERROR;
|
|
+ continue;
|
|
+ } else {
|
|
+ goto error;
|
|
+ }
|
|
+ }
|
|
+ else continue;
|
|
+ } else if (!strcmp(key, "nomail")) {
|
|
+ freeLogItem(logAddress);
|
|
+ } else if (!strcmp(key, "missingok")) {
|
|
+ newlog->flags |= LOG_FLAG_MISSINGOK;
|
|
+ } else if (!strcmp(key, "nomissingok")) {
|
|
+ newlog->flags &= ~LOG_FLAG_MISSINGOK;
|
|
+ } else if (!strcmp(key, "prerotate")) {
|
|
+ freeLogItem (pre);
|
|
+ scriptStart = start;
|
|
+ scriptDest = &newlog->pre;
|
|
+ state = STATE_LOAD_SCRIPT;
|
|
+ } else if (!strcmp(key, "firstaction")) {
|
|
+ freeLogItem (first);
|
|
+ scriptStart = start;
|
|
+ scriptDest = &newlog->first;
|
|
+ state = STATE_LOAD_SCRIPT;
|
|
+ } else if (!strcmp(key, "postrotate")) {
|
|
+ freeLogItem (post);
|
|
+ scriptStart = start;
|
|
+ scriptDest = &newlog->post;
|
|
+ state = STATE_LOAD_SCRIPT;
|
|
+ } else if (!strcmp(key, "lastaction")) {
|
|
+ freeLogItem (last);
|
|
+ scriptStart = start;
|
|
+ scriptDest = &newlog->last;
|
|
+ state = STATE_LOAD_SCRIPT;
|
|
+ } else if (!strcmp(key, "tabooext")) {
|
|
+ if (newlog != defConfig) {
|
|
+ message(MESS_ERROR,
|
|
+ "%s:%d tabooext may not appear inside "
|
|
+ "of log file definition\n", configFile,
|
|
+ lineNum);
|
|
+ state = STATE_ERROR;
|
|
+ continue;
|
|
+ }
|
|
+ free(key);
|
|
+ if ((key = isolateValue(configFile, lineNum, "tabooext", &start,
|
|
+ &buf, length)) != NULL) {
|
|
|
|
- *endtag = oldchar, start = endtag;
|
|
- } else if (!strcmp(start, "delaycompress")) {
|
|
- newlog->flags |= LOG_FLAG_DELAYCOMPRESS;
|
|
+ if (*key == '+') {
|
|
+ key++;
|
|
+ while (isspace(*key) && *key)
|
|
+ key++;
|
|
+ } else {
|
|
+ free_2d_array(tabooExts, tabooCount);
|
|
+ tabooCount = 0;
|
|
+ tabooExts = malloc(1);
|
|
+ }
|
|
|
|
- *endtag = oldchar, start = endtag;
|
|
- } else if (!strcmp(start, "nodelaycompress")) {
|
|
- newlog->flags &= ~LOG_FLAG_DELAYCOMPRESS;
|
|
+ endtag = key;
|
|
+ while (*endtag) {
|
|
+ chptr = endtag;
|
|
+ while (!isspace(*chptr) && *chptr != ',' && *chptr)
|
|
+ chptr++;
|
|
|
|
- *endtag = oldchar, start = endtag;
|
|
- } else if (!strcmp(start, "shred")) {
|
|
- newlog->flags |= LOG_FLAG_SHRED;
|
|
+ tabooExts = realloc(tabooExts, sizeof(*tabooExts) *
|
|
+ (tabooCount + 1));
|
|
+ tabooExts[tabooCount] = malloc(chptr - endtag + 1);
|
|
+ strncpy(tabooExts[tabooCount], endtag,
|
|
+ chptr - endtag);
|
|
+ tabooExts[tabooCount][chptr - endtag] = '\0';
|
|
+ tabooCount++;
|
|
|
|
- *endtag = oldchar, start = endtag;
|
|
- } else if (!strcmp(start, "noshred")) {
|
|
- newlog->flags &= ~LOG_FLAG_SHRED;
|
|
+ endtag = chptr;
|
|
+ if (*endtag == ',')
|
|
+ start++;
|
|
+ while (isspace(*endtag) && *endtag)
|
|
+ endtag++;
|
|
+ }
|
|
+ }
|
|
+ else continue;
|
|
+ } else if (!strcmp(key, "include")) {
|
|
+ free(key);
|
|
+ if ((key = isolateValue(configFile, lineNum, "include", &start,
|
|
+ &buf, length)) != NULL) {
|
|
|
|
- *endtag = oldchar, start = endtag;
|
|
- } else if (!strcmp(start, "sharedscripts")) {
|
|
- newlog->flags |= LOG_FLAG_SHAREDSCRIPTS;
|
|
+ message(MESS_DEBUG, "including %s\n", key);
|
|
+ if (++recursion_depth > MAX_NESTING) {
|
|
+ message(MESS_ERROR, "%s:%d include nesting too deep\n",
|
|
+ configFile, lineNum);
|
|
+ --recursion_depth;
|
|
+ goto error;
|
|
+ }
|
|
+ if (readConfigPath(key, newlog)) {
|
|
+ --recursion_depth;
|
|
+ goto error;
|
|
+ }
|
|
+ --recursion_depth;
|
|
+ }
|
|
+ else continue;
|
|
+ } else if (!strcmp(key, "olddir")) {
|
|
+ freeLogItem (oldDir);
|
|
|
|
- *endtag = oldchar, start = endtag;
|
|
- } else if (!strcmp(start, "nosharedscripts")) {
|
|
- newlog->flags &= ~LOG_FLAG_SHAREDSCRIPTS;
|
|
+ if (!(newlog->oldDir = readPath(configFile, lineNum,
|
|
+ "olddir", &start, &buf, length))) {
|
|
+ if (newlog != defConfig) {
|
|
+ state = STATE_ERROR;
|
|
+ continue;
|
|
+ } else {
|
|
+ goto error;
|
|
+ }
|
|
+ }
|
|
+ else continue;
|
|
+#if 0
|
|
+ if (stat(newlog->oldDir, &sb)) {
|
|
+ message(MESS_ERROR, "%s:%d error verifying olddir "
|
|
+ "path %s: %s\n", configFile, lineNum,
|
|
+ newlog->oldDir, strerror(errno));
|
|
+ free(newlog->oldDir);
|
|
+ goto error;
|
|
+ }
|
|
|
|
- *endtag = oldchar, start = endtag;
|
|
- } else if (!strcmp(start, "copytruncate")) {
|
|
- newlog->flags |= LOG_FLAG_COPYTRUNCATE;
|
|
+ if (!S_ISDIR(sb.st_mode)) {
|
|
+ message(MESS_ERROR, "%s:%d olddir path %s is not a "
|
|
+ "directory\n", configFile, lineNum,
|
|
+ newlog->oldDir);
|
|
+ free(newlog->oldDir);
|
|
+ goto error;
|
|
+ }
|
|
+#endif
|
|
+ message(MESS_DEBUG, "olddir is now %s\n", newlog->oldDir);
|
|
+ } else if (!strcmp(key, "extension")) {
|
|
+ if ((key = isolateValue
|
|
+ (configFile, lineNum, "extension name", &start,
|
|
+ &buf, length)) != NULL) {
|
|
+ freeLogItem (extension);
|
|
+ newlog->extension = key;
|
|
+ key = NULL;
|
|
+ }
|
|
+ else continue;
|
|
|
|
- *endtag = oldchar, start = endtag;
|
|
- } else if (!strcmp(start, "nocopytruncate")) {
|
|
- newlog->flags &= ~LOG_FLAG_COPYTRUNCATE;
|
|
+ message(MESS_DEBUG, "extension is now %s\n",
|
|
+ newlog->extension);
|
|
|
|
- *endtag = oldchar, start = endtag;
|
|
- } else if (!strcmp(start, "copy")) {
|
|
- newlog->flags |= LOG_FLAG_COPY;
|
|
+ } else if (!strcmp(key, "compresscmd")) {
|
|
+ freeLogItem (compress_prog);
|
|
|
|
- *endtag = oldchar, start = endtag;
|
|
- } else if (!strcmp(start, "nocopy")) {
|
|
- newlog->flags &= ~LOG_FLAG_COPY;
|
|
+ if (!
|
|
+ (newlog->compress_prog =
|
|
+ readPath(configFile, lineNum, "compress", &start, &buf, length))) {
|
|
+ if (newlog != defConfig) {
|
|
+ state = STATE_ERROR;
|
|
+ continue;
|
|
+ } else {
|
|
+ goto error;
|
|
+ }
|
|
+ }
|
|
+ else continue;
|
|
|
|
- *endtag = oldchar, start = endtag;
|
|
- } else if (!strcmp(start, "ifempty")) {
|
|
- newlog->flags |= LOG_FLAG_IFEMPTY;
|
|
+ if (access(newlog->compress_prog, X_OK)) {
|
|
+ message(MESS_ERROR,
|
|
+ "%s:%d compression program %s is not an executable file\n",
|
|
+ configFile, lineNum, newlog->compress_prog);
|
|
+ if (newlog != defConfig) {
|
|
+ state = STATE_ERROR;
|
|
+ continue;
|
|
+ } else {
|
|
+ goto error;
|
|
+ }
|
|
+ }
|
|
|
|
- *endtag = oldchar, start = endtag;
|
|
- } else if (!strcmp(start, "notifempty")) {
|
|
- newlog->flags &= ~LOG_FLAG_IFEMPTY;
|
|
+ message(MESS_DEBUG, "compress_prog is now %s\n",
|
|
+ newlog->compress_prog);
|
|
|
|
- *endtag = oldchar, start = endtag;
|
|
- } else if (!strcmp(start, "dateext")) {
|
|
- newlog->flags |= LOG_FLAG_DATEEXT;
|
|
+ } else if (!strcmp(key, "uncompresscmd")) {
|
|
+ freeLogItem (uncompress_prog);
|
|
|
|
- *endtag = oldchar, start = endtag;
|
|
- } else if (!strcmp(start, "nodateext")) {
|
|
- newlog->flags &= ~LOG_FLAG_DATEEXT;
|
|
-
|
|
- *endtag = oldchar, start = endtag;
|
|
- } else if (!strcmp(start, "dateformat")) {
|
|
- *endtag = oldchar, start = endtag;
|
|
-
|
|
- endtag = start;
|
|
- while (*endtag != '\n')
|
|
- endtag++;
|
|
- while (isspace(*endtag))
|
|
- endtag--;
|
|
- endtag++;
|
|
- oldchar = *endtag, *endtag = '\0';
|
|
+ if (!
|
|
+ (newlog->uncompress_prog =
|
|
+ readPath(configFile, lineNum, "uncompress",
|
|
+ &start, &buf, length))) {
|
|
+ if (newlog != defConfig) {
|
|
+ state = STATE_ERROR;
|
|
+ continue;
|
|
+ } else {
|
|
+ goto error;
|
|
+ }
|
|
+ }
|
|
+ else continue;
|
|
|
|
- freeLogItem(dateformat);
|
|
- newlog->dateformat = strdup(start);
|
|
+ if (access(newlog->uncompress_prog, X_OK)) {
|
|
+ message(MESS_ERROR,
|
|
+ "%s:%d uncompression program %s is not an executable file\n",
|
|
+ configFile, lineNum, newlog->uncompress_prog);
|
|
+ if (newlog != defConfig) {
|
|
+ state = STATE_ERROR;
|
|
+ continue;
|
|
+ } else {
|
|
+ goto error;
|
|
+ }
|
|
+ }
|
|
|
|
- *endtag = oldchar, start = endtag;
|
|
- } else if (!strcmp(start, "noolddir")) {
|
|
- newlog->oldDir = NULL;
|
|
+ message(MESS_DEBUG, "uncompress_prog is now %s\n",
|
|
+ newlog->uncompress_prog);
|
|
|
|
- *endtag = oldchar, start = endtag;
|
|
- } else if (!strcmp(start, "mailfirst")) {
|
|
- newlog->flags |= LOG_FLAG_MAILFIRST;
|
|
+ } else if (!strcmp(key, "compressoptions")) {
|
|
+ char *options;
|
|
|
|
- *endtag = oldchar, start = endtag;
|
|
- } else if (!strcmp(start, "maillast")) {
|
|
- newlog->flags &= ~LOG_FLAG_MAILFIRST;
|
|
+ if (newlog->compress_options_list) {
|
|
+ free(newlog->compress_options_list);
|
|
+ newlog->compress_options_list = NULL;
|
|
+ newlog->compress_options_count = 0;
|
|
+ }
|
|
|
|
- *endtag = oldchar, start = endtag;
|
|
- } else if (!strcmp(start, "create")) {
|
|
- *endtag = oldchar, start = endtag;
|
|
+ if (!
|
|
+ (options =
|
|
+ readPath(configFile, lineNum, "compressoptions",
|
|
+ &start, &buf, length))) {
|
|
+ if (newlog != defConfig) {
|
|
+ state = STATE_ERROR;
|
|
+ continue;
|
|
+ } else {
|
|
+ goto error;
|
|
+ }
|
|
+ } else continue;
|
|
|
|
- endtag = start;
|
|
- while (*endtag != '\n')
|
|
- endtag++;
|
|
- while (isspace(*endtag))
|
|
- endtag--;
|
|
- endtag++;
|
|
- oldchar = *endtag, *endtag = '\0';
|
|
+ if (poptParseArgvString(options,
|
|
+ &newlog->compress_options_count,
|
|
+ &newlog->compress_options_list)) {
|
|
+ message(MESS_ERROR,
|
|
+ "%s:%d invalid compression options\n",
|
|
+ configFile, lineNum);
|
|
+ free(options);
|
|
+ if (newlog != defConfig) {
|
|
+ state = STATE_ERROR;
|
|
+ continue;
|
|
+ } else {
|
|
+ goto error;
|
|
+ }
|
|
+ }
|
|
|
|
- rc = sscanf(start, "%o %s %s%c", &createMode,
|
|
- createOwner, createGroup, &foo);
|
|
- if (rc == 4) {
|
|
- message(MESS_ERROR, "%s:%d extra arguments for "
|
|
- "create\n", configFile, lineNum);
|
|
- if (newlog != defConfig) {
|
|
- *endtag = oldchar, start = endtag;
|
|
- logerror = 1;
|
|
- continue;
|
|
- } else {
|
|
- goto error;
|
|
- }
|
|
- }
|
|
+ message(MESS_DEBUG, "compress_options is now %s\n",
|
|
+ options);
|
|
+ free(options);
|
|
+ } else if (!strcmp(key, "compressext")) {
|
|
+ freeLogItem (compress_ext);
|
|
|
|
- if (rc > 0)
|
|
- newlog->createMode = createMode;
|
|
+ if (!
|
|
+ (newlog->compress_ext =
|
|
+ readPath(configFile, lineNum, "compress-ext",
|
|
+ &start, &buf, length))) {
|
|
+ if (newlog != defConfig) {
|
|
+ state = STATE_ERROR;
|
|
+ continue;
|
|
+ } else {
|
|
+ goto error;
|
|
+ }
|
|
+ } else continue;
|
|
|
|
- if (rc > 1) {
|
|
- pw = getpwnam(createOwner);
|
|
- if (!pw) {
|
|
- message(MESS_ERROR, "%s:%d unknown user '%s'\n",
|
|
- configFile, lineNum, createOwner);
|
|
- if (newlog != defConfig) {
|
|
- *endtag = oldchar, start = endtag;
|
|
- logerror = 1;
|
|
- continue;
|
|
- } else {
|
|
- goto error;
|
|
- }
|
|
- }
|
|
- newlog->createUid = pw->pw_uid;
|
|
- endpwent();
|
|
- }
|
|
- if (rc > 2) {
|
|
- group = getgrnam(createGroup);
|
|
- if (!group) {
|
|
- message(MESS_ERROR, "%s:%d unknown group '%s'\n",
|
|
- configFile, lineNum, createGroup);
|
|
- if (newlog != defConfig) {
|
|
- *endtag = oldchar, start = endtag;
|
|
- logerror = 1;
|
|
- continue;
|
|
- } else {
|
|
- goto error;
|
|
- }
|
|
- }
|
|
- newlog->createGid = group->gr_gid;
|
|
- endgrent();
|
|
- }
|
|
+ message(MESS_DEBUG, "compress_ext is now %s\n",
|
|
+ newlog->compress_ext);
|
|
+ } else {
|
|
+ message(MESS_ERROR, "%s:%d unknown option '%s' "
|
|
+ "-- ignoring line\n", configFile, lineNum, key);
|
|
+ if (*start != '\n')
|
|
+ state = STATE_SKIP_LINE;
|
|
+ }
|
|
+ free(key);
|
|
+ key = NULL;
|
|
+ } else if (*start == '/' || *start == '"' || *start == '\'') {
|
|
+ if (newlog != defConfig) {
|
|
+ message(MESS_ERROR, "%s:%d unexpected log filename\n",
|
|
+ configFile, lineNum);
|
|
+ state = STATE_ERROR;
|
|
+ continue;
|
|
+ }
|
|
|
|
- newlog->flags |= LOG_FLAG_CREATE;
|
|
+ /* If no compression options were found in config file, set
|
|
+ default values */
|
|
+ if (!newlog->compress_prog)
|
|
+ newlog->compress_prog = strdup(COMPRESS_COMMAND);
|
|
+ if (!newlog->uncompress_prog)
|
|
+ newlog->uncompress_prog = strdup(UNCOMPRESS_COMMAND);
|
|
+ if (!newlog->compress_ext)
|
|
+ newlog->compress_ext = strdup(COMPRESS_EXT);
|
|
|
|
- *endtag = oldchar, start = endtag;
|
|
- } else if (!strcmp(start, "nocreate")) {
|
|
- newlog->flags &= ~LOG_FLAG_CREATE;
|
|
+ /* Allocate a new logInfo structure and insert it into the logs
|
|
+ queue, copying the actual values from defConfig */
|
|
+ if ((newlog = newLogInfo(defConfig)) == NULL)
|
|
+ goto error;
|
|
|
|
- *endtag = oldchar, start = endtag;
|
|
- } else if (!strcmp(start, "size") || !strcmp(start, "minsize")) {
|
|
- unsigned long long size = 0;
|
|
- char *opt = start;
|
|
- *endtag = oldchar, start = endtag;
|
|
+ endtag = start;
|
|
+ while (endtag - buf < length && *endtag != '{' && *endtag != '\0') {
|
|
+ endtag++;}
|
|
+ if (endtag - buf > length)
|
|
+ continue;
|
|
+ char *key = strndup(start, endtag - start);
|
|
+ start = endtag;
|
|
|
|
- if (!isolateValue(configFile, lineNum, opt, &start,
|
|
- &endtag)) {
|
|
- oldchar = *endtag, *endtag = '\0';
|
|
+ if (poptParseArgvString(key, &argc, &argv)) {
|
|
+ message(MESS_ERROR, "%s:%d error parsing filename\n",
|
|
+ configFile, lineNum);
|
|
+ free(key);
|
|
+ goto error;
|
|
+ } else if (argc < 1) {
|
|
+ message(MESS_ERROR,
|
|
+ "%s:%d { expected after log file name(s)\n",
|
|
+ configFile, lineNum);
|
|
+ free(key);
|
|
+ goto error;
|
|
+ }
|
|
|
|
- length = strlen(start) - 1;
|
|
- if (start[length] == 'k') {
|
|
- start[length] = '\0';
|
|
- multiplier = 1024;
|
|
- } else if (start[length] == 'M') {
|
|
- start[length] = '\0';
|
|
- multiplier = 1024 * 1024;
|
|
- } else if (start[length] == 'G') {
|
|
- start[length] = '\0';
|
|
- multiplier = 1024 * 1024 * 1024;
|
|
- } else if (!isdigit(start[length])) {
|
|
- message(MESS_ERROR, "%s:%d unknown unit '%c'\n",
|
|
- configFile, lineNum, start[length]);
|
|
- if (newlog != defConfig) {
|
|
- *endtag = oldchar, start = endtag;
|
|
- logerror = 1;
|
|
- continue;
|
|
- } else {
|
|
- goto error;
|
|
- }
|
|
- } else {
|
|
- multiplier = 1;
|
|
- }
|
|
+ newlog->files = NULL;
|
|
+ newlog->numFiles = 0;
|
|
+ for (argNum = 0; argNum < argc && logerror != 1; argNum++) {
|
|
+ if (globerr_msg) {
|
|
+ free(globerr_msg);
|
|
+ globerr_msg = NULL;
|
|
+ }
|
|
+
|
|
+ rc = glob(argv[argNum], GLOB_NOCHECK, globerr,
|
|
+ &globResult);
|
|
+ if (rc == GLOB_ABORTED) {
|
|
+ if (newlog->flags & LOG_FLAG_MISSINGOK) {
|
|
+ continue;
|
|
+ }
|
|
|
|
- size = multiplier * strtoul(start, &chptr, 0);
|
|
- if (*chptr) {
|
|
- message(MESS_ERROR, "%s:%d bad size '%s'\n",
|
|
- configFile, lineNum, start);
|
|
- if (newlog != defConfig) {
|
|
- *endtag = oldchar, start = endtag;
|
|
- logerror = 1;
|
|
- continue;
|
|
- } else {
|
|
- goto error;
|
|
- }
|
|
- }
|
|
+ /* We don't yet know whether this stanza has "missingok"
|
|
+ * set, so store the error message for later. */
|
|
+ rc = asprintf(&globerr_msg, "%s:%d glob failed for %s: %s\n",
|
|
+ configFile, lineNum, argv[argNum], strerror(glob_errno));
|
|
+ if (rc == -1)
|
|
+ globerr_msg = NULL;
|
|
+
|
|
+ globResult.gl_pathc = 0;
|
|
+ }
|
|
|
|
- if (!strncmp(opt, "size", 4)) {
|
|
- newlog->criterium = ROT_SIZE;
|
|
- newlog->threshhold = size;
|
|
- } else
|
|
- newlog->minsize = size;
|
|
+ newlog->files =
|
|
+ realloc(newlog->files,
|
|
+ sizeof(*newlog->files) * (newlog->numFiles +
|
|
+ globResult.
|
|
+ gl_pathc));
|
|
|
|
- *endtag = oldchar, start = endtag;
|
|
- }
|
|
-#if 0 /* this seems like such a good idea :-( */
|
|
- } else if (!strcmp(start, "days")) {
|
|
- *endtag = oldchar, start = endtag;
|
|
+ for (i = 0; i < globResult.gl_pathc; i++) {
|
|
+ /* if we glob directories we can get false matches */
|
|
+ if (!lstat(globResult.gl_pathv[i], &sb) &&
|
|
+ S_ISDIR(sb.st_mode)) {
|
|
+ continue;
|
|
+ }
|
|
|
|
- if (!isolateValue(configFile, lineNum, "size", &start,
|
|
- &endtag)) {
|
|
- oldchar = *endtag, *endtag = '\0';
|
|
+ for (log = logs.tqh_first; log != NULL;
|
|
+ log = log->list.tqe_next) {
|
|
+ for (k = 0; k < log->numFiles; k++) {
|
|
+ if (!strcmp(log->files[k],
|
|
+ globResult.gl_pathv[i])) {
|
|
+ message(MESS_ERROR,
|
|
+ "%s:%d duplicate log entry for %s\n",
|
|
+ configFile, lineNum,
|
|
+ globResult.gl_pathv[i]);
|
|
+ logerror = 1;
|
|
+ goto duperror;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
|
|
- newlog->threshhold = strtoul(start, &chptr, 0);
|
|
- if (*chptr) {
|
|
- message(MESS_ERROR,
|
|
- "%s:%d bad number of days'%s'\n",
|
|
- configFile, lineNum, start);
|
|
- goto error;
|
|
- }
|
|
+ newlog->files[newlog->numFiles] =
|
|
+ strdup(globResult.gl_pathv[i]);
|
|
+ newlog->numFiles++;
|
|
+ }
|
|
+ duperror:
|
|
+ globfree(&globResult);
|
|
+ }
|
|
|
|
- newlog->criterium = ROT_DAYS;
|
|
+ newlog->pattern = key;
|
|
|
|
- *endtag = oldchar, start = endtag;
|
|
- }
|
|
-#endif
|
|
- } else if (!strcmp(start, "shredcycles")) {
|
|
- *endtag = oldchar, start = endtag;
|
|
+// if (!logerror)
|
|
+// message(MESS_DEBUG, "reading config info for %s\n", start);
|
|
|
|
- if (!isolateValue(configFile, lineNum, "shred cycles",
|
|
- &start, &endtag)) {
|
|
- oldchar = *endtag, *endtag = '\0';
|
|
+ free(argv);
|
|
|
|
- newlog->shred_cycles = strtoul(start, &chptr, 0);
|
|
- if (*chptr || newlog->shred_cycles < 0) {
|
|
- message(MESS_ERROR, "%s:%d bad shred cycles '%s'\n",
|
|
- configFile, lineNum, start);
|
|
- goto error;
|
|
- }
|
|
- *endtag = oldchar, start = endtag;
|
|
- }
|
|
- } else if (!strcmp(start, "daily")) {
|
|
- *endtag = oldchar, start = endtag;
|
|
+// start = endtag + 1;
|
|
+ } else if (*start == '}') {
|
|
+ if (newlog == defConfig) {
|
|
+ message(MESS_ERROR, "%s:%d unexpected }\n", configFile,
|
|
+ lineNum);
|
|
+ goto error;
|
|
+ }
|
|
+ if (globerr_msg) {
|
|
+ if (!(newlog->flags & LOG_FLAG_MISSINGOK))
|
|
+ message(MESS_ERROR, globerr_msg);
|
|
+ free(globerr_msg);
|
|
+ globerr_msg = NULL;
|
|
+ if (!(newlog->flags & LOG_FLAG_MISSINGOK))
|
|
+ return 1;
|
|
+ }
|
|
|
|
- newlog->criterium = ROT_DAYS;
|
|
- newlog->threshhold = 1;
|
|
- } else if (!strcmp(start, "monthly")) {
|
|
- *endtag = oldchar, start = endtag;
|
|
+ if (newlog->oldDir) {
|
|
+ for (i = 0; i < newlog->numFiles; i++) {
|
|
+ char *ld;
|
|
+ dirName = ourDirName(newlog->files[i]);
|
|
+ if (stat(dirName, &sb2)) {
|
|
+ message(MESS_ERROR,
|
|
+ "%s:%d error verifying log file "
|
|
+ "path %s: %s\n", configFile, lineNum,
|
|
+ dirName, strerror(errno));
|
|
+ free(dirName);
|
|
+ goto error;
|
|
+ }
|
|
+ ld = alloca(strlen(dirName) + strlen(newlog->oldDir) +
|
|
+ 2);
|
|
+ sprintf(ld, "%s/%s", dirName, newlog->oldDir);
|
|
+ free(dirName);
|
|
|
|
- newlog->criterium = ROT_MONTHLY;
|
|
- } else if (!strcmp(start, "weekly")) {
|
|
- *endtag = oldchar, start = endtag;
|
|
+ if (newlog->oldDir[0] != '/')
|
|
+ dirName = ld;
|
|
+ else
|
|
+ dirName = newlog->oldDir;
|
|
+ if (stat(dirName, &sb)) {
|
|
+ message(MESS_ERROR, "%s:%d error verifying olddir "
|
|
+ "path %s: %s\n", configFile, lineNum,
|
|
+ dirName, strerror(errno));
|
|
+ goto error;
|
|
+ }
|
|
|
|
- newlog->criterium = ROT_WEEKLY;
|
|
- } else if (!strcmp(start, "yearly")) {
|
|
- *endtag = oldchar, start = endtag;
|
|
+ if (sb.st_dev != sb2.st_dev) {
|
|
+ message(MESS_ERROR,
|
|
+ "%s:%d olddir %s and log file %s "
|
|
+ "are on different devices\n", configFile,
|
|
+ lineNum, newlog->oldDir, newlog->files[i]);
|
|
+ goto error;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
|
|
- newlog->criterium = ROT_YEARLY;
|
|
- } else if (!strcmp(start, "rotate")) {
|
|
- *endtag = oldchar, start = endtag;
|
|
-
|
|
- if (!isolateValue
|
|
- (configFile, lineNum, "rotate count", &start,
|
|
- &endtag)) {
|
|
- oldchar = *endtag, *endtag = '\0';
|
|
-
|
|
- newlog->rotateCount = strtoul(start, &chptr, 0);
|
|
- if (*chptr || newlog->rotateCount < 0) {
|
|
- message(MESS_ERROR,
|
|
- "%s:%d bad rotation count '%s'\n",
|
|
- configFile, lineNum, start);
|
|
- if (newlog != defConfig) {
|
|
- *endtag = oldchar, start = endtag;
|
|
- logerror = 1;
|
|
- continue;
|
|
- } else {
|
|
- goto error;
|
|
+ newlog = defConfig;
|
|
+ state = STATE_DEFINITION_END;
|
|
+ } else if (*start != '\n') {
|
|
+ message(MESS_ERROR, "%s:%d lines must begin with a keyword "
|
|
+ "or a filename (possibly in double quotes)\n",
|
|
+ configFile, lineNum);
|
|
+ state = STATE_SKIP_LINE;
|
|
}
|
|
- }
|
|
- *endtag = oldchar, start = endtag;
|
|
- }
|
|
- } else if (!strcmp(start, "start")) {
|
|
- *endtag = oldchar, start = endtag;
|
|
-
|
|
- if (!isolateValue
|
|
- (configFile, lineNum, "start count", &start,
|
|
- &endtag)) {
|
|
- oldchar = *endtag, *endtag = '\0';
|
|
-
|
|
- newlog->logStart = strtoul(start, &chptr, 0);
|
|
- if (*chptr || newlog->logStart < 0) {
|
|
- message(MESS_ERROR, "%s:%d bad start count '%s'\n",
|
|
- configFile, lineNum, start);
|
|
- if (newlog != defConfig) {
|
|
- *endtag = oldchar, start = endtag;
|
|
- logerror = 1;
|
|
- continue;
|
|
- } else {
|
|
- goto error;
|
|
+ break;
|
|
+ case STATE_SKIP_LINE:
|
|
+ case STATE_SKIP_LINE | STATE_SKIP_CONFIG:
|
|
+ if (*start == '\n')
|
|
+ state = state & STATE_SKIP_CONFIG ? STATE_SKIP_CONFIG : STATE_DEFAULT;
|
|
+ break;
|
|
+ case STATE_SKIP_LINE | STATE_LOAD_SCRIPT:
|
|
+ if (*start == '\n')
|
|
+ state = STATE_LOAD_SCRIPT;
|
|
+ break;
|
|
+ case STATE_SKIP_LINE | STATE_LOAD_SCRIPT | STATE_SKIP_CONFIG:
|
|
+ if (*start == '\n')
|
|
+ state = STATE_LOAD_SCRIPT | STATE_SKIP_CONFIG;
|
|
+ break;
|
|
+ case STATE_DEFINITION_END:
|
|
+ case STATE_DEFINITION_END | STATE_SKIP_CONFIG:
|
|
+ if (isblank(*start))
|
|
+ continue;
|
|
+ if (*start != '\n') {
|
|
+ message(MESS_ERROR, "%s:%d, unexpected text after }\n",
|
|
+ configFile, lineNum);
|
|
+ state = STATE_SKIP_LINE | (state & STATE_SKIP_CONFIG ? STATE_SKIP_CONFIG : 0);
|
|
}
|
|
- }
|
|
- *endtag = oldchar, start = endtag;
|
|
- }
|
|
- } else if (!strcmp(start, "maxage")) {
|
|
- *endtag = oldchar, start = endtag;
|
|
+ else
|
|
+ state = state & STATE_SKIP_CONFIG ? STATE_SKIP_CONFIG : STATE_DEFAULT;
|
|
+ break;
|
|
+ case STATE_ERROR:
|
|
+ assert(newlog != defConfig);
|
|
|
|
- if (!isolateValue
|
|
- (configFile, lineNum, "maxage count", &start,
|
|
- &endtag)) {
|
|
- oldchar = *endtag, *endtag = '\0';
|
|
+ message(MESS_ERROR, "found error in %s, skipping\n",
|
|
+ newlog->pattern ? newlog->pattern : "log config");
|
|
|
|
- newlog->rotateAge = strtoul(start, &chptr, 0);
|
|
- if (*chptr || newlog->rotateAge < 0) {
|
|
- message(MESS_ERROR, "%s:%d bad maximum age '%s'\n",
|
|
- configFile, lineNum, start);
|
|
- if (newlog != defConfig) {
|
|
- *endtag = oldchar, start = endtag;
|
|
- logerror = 1;
|
|
- continue;
|
|
- } else {
|
|
- goto error;
|
|
- }
|
|
- }
|
|
- *endtag = oldchar, start = endtag;
|
|
- }
|
|
- } else if (!strcmp(start, "errors")) {
|
|
- message(MESS_DEBUG,
|
|
- "%s: %d: the errors directive is deprecated and no longer used.\n",
|
|
- configFile, lineNum);
|
|
- } else if (!strcmp(start, "mail")) {
|
|
- *endtag = oldchar, start = endtag;
|
|
- freeLogItem(logAddress);
|
|
- if (!(newlog->logAddress = readAddress(configFile, lineNum,
|
|
- "mail", &start))) {
|
|
- if (newlog != defConfig) {
|
|
- logerror = 1;
|
|
- continue;
|
|
- } else {
|
|
- goto error;
|
|
- }
|
|
- }
|
|
- } else if (!strcmp(start, "nomail")) {
|
|
- freeLogItem(logAddress);
|
|
+ state = STATE_SKIP_CONFIG;
|
|
+ break;
|
|
+ case STATE_LOAD_SCRIPT:
|
|
+ case STATE_LOAD_SCRIPT | STATE_SKIP_CONFIG:
|
|
+ if ((key = isolateWord(&start, &buf, length)) == NULL)
|
|
+ continue;
|
|
|
|
- *endtag = oldchar, start = endtag;
|
|
- } else if (!strcmp(start, "missingok")) {
|
|
- newlog->flags |= LOG_FLAG_MISSINGOK;
|
|
+ if (strcmp(key, "endscript") == 0) {
|
|
+ if (state & STATE_SKIP_CONFIG) {
|
|
+ state = STATE_SKIP_CONFIG;
|
|
+ }
|
|
+ else {
|
|
+ endtag = start - 9;
|
|
+ while (*endtag != '\n')
|
|
+ endtag--;
|
|
+ endtag++;
|
|
+ *scriptDest = malloc(endtag - scriptStart + 1);
|
|
+ strncpy(*scriptDest, scriptStart,
|
|
+ endtag - scriptStart);
|
|
+ (*scriptDest)[endtag - scriptStart] = '\0';
|
|
|
|
- *endtag = oldchar, start = endtag;
|
|
- } else if (!strcmp(start, "nomissingok")) {
|
|
- newlog->flags &= ~LOG_FLAG_MISSINGOK;
|
|
-
|
|
- *endtag = oldchar, start = endtag;
|
|
- } else if (!strcmp(start, "prerotate")) {
|
|
- *endtag = oldchar, start = endtag;
|
|
-
|
|
- freeLogItem (pre);
|
|
-
|
|
- scriptStart = start;
|
|
- scriptDest = &newlog->pre;
|
|
-
|
|
- while (*start != '\n')
|
|
- start++;
|
|
- } else if (!strcmp(start, "firstaction")) {
|
|
- *endtag = oldchar, start = endtag;
|
|
-
|
|
- freeLogItem (first);
|
|
-
|
|
- scriptStart = start;
|
|
- scriptDest = &newlog->first;
|
|
-
|
|
- while (*start != '\n')
|
|
- start++;
|
|
- } else if (!strcmp(start, "postrotate")) {
|
|
- *endtag = oldchar, start = endtag;
|
|
-
|
|
- freeLogItem (post);
|
|
-
|
|
- scriptStart = start;
|
|
- scriptDest = &newlog->post;
|
|
-
|
|
- while (*start != '\n')
|
|
- start++;
|
|
- } else if (!strcmp(start, "lastaction")) {
|
|
- *endtag = oldchar, start = endtag;
|
|
-
|
|
- freeLogItem (last);
|
|
-
|
|
- scriptStart = start;
|
|
- scriptDest = &newlog->last;
|
|
-
|
|
- while (*start != '\n')
|
|
- start++;
|
|
- } else if (!strcmp(start, "tabooext")) {
|
|
- if (newlog != defConfig) {
|
|
- message(MESS_ERROR,
|
|
- "%s:%d tabooext may not appear inside "
|
|
- "of log file definition\n", configFile,
|
|
- lineNum);
|
|
- *endtag = oldchar, start = endtag;
|
|
- logerror = 1;
|
|
- continue;
|
|
- }
|
|
-
|
|
- *endtag = oldchar, start = endtag;
|
|
- if (!isolateValue(configFile, lineNum, "tabooext", &start,
|
|
- &endtag)) {
|
|
- oldchar = *endtag, *endtag = '\0';
|
|
-
|
|
- if (*start == '+') {
|
|
- start++;
|
|
- while (isspace(*start) && *start)
|
|
- start++;
|
|
- } else {
|
|
- free_2d_array(tabooExts, tabooCount);
|
|
- tabooCount = 0;
|
|
- tabooExts = malloc(1);
|
|
- }
|
|
-
|
|
- while (*start) {
|
|
- chptr = start;
|
|
- while (!isspace(*chptr) && *chptr != ',' && *chptr)
|
|
- chptr++;
|
|
-
|
|
- tabooExts = realloc(tabooExts, sizeof(*tabooExts) *
|
|
- (tabooCount + 1));
|
|
- tabooExts[tabooCount] = malloc(chptr - start + 1);
|
|
- strncpy(tabooExts[tabooCount], start,
|
|
- chptr - start);
|
|
- tabooExts[tabooCount][chptr - start] = '\0';
|
|
- tabooCount++;
|
|
-
|
|
- start = chptr;
|
|
- if (*start == ',')
|
|
- start++;
|
|
- while (isspace(*start) && *start)
|
|
- start++;
|
|
- }
|
|
-
|
|
- *endtag = oldchar, start = endtag;
|
|
- }
|
|
- } else if (!strcmp(start, "include")) {
|
|
-// if (newlog != defConfig) {
|
|
-// message(MESS_ERROR,
|
|
-// "%s:%d include may not appear inside "
|
|
-// "of log file definition\n", configFile,
|
|
-// lineNum);
|
|
-// *endtag = oldchar, start = endtag;
|
|
-// logerror = 1;
|
|
-// continue;
|
|
-// }
|
|
-
|
|
- *endtag = oldchar, start = endtag;
|
|
- if (!isolateValue(configFile, lineNum, "include", &start,
|
|
- &endtag)) {
|
|
- oldchar = *endtag, *endtag = '\0';
|
|
-
|
|
- message(MESS_DEBUG, "including %s\n", start);
|
|
- if (++recursion_depth > MAX_NESTING) {
|
|
- message(MESS_ERROR, "%s:%d include nesting too deep\n",
|
|
- configFile, lineNum);
|
|
- --recursion_depth;
|
|
- goto error;
|
|
+ scriptDest = NULL;
|
|
+ scriptStart = NULL;
|
|
+ }
|
|
+ state = state & STATE_SKIP_CONFIG ? STATE_SKIP_CONFIG : STATE_DEFAULT;
|
|
}
|
|
- if (readConfigPath(start, newlog)) {
|
|
- --recursion_depth;
|
|
- goto error;
|
|
+ else {
|
|
+ state = (*start == '\n' ? 0 : STATE_SKIP_LINE) |
|
|
+ STATE_LOAD_SCRIPT |
|
|
+ (state & STATE_SKIP_CONFIG ? STATE_SKIP_CONFIG : 0);
|
|
}
|
|
- --recursion_depth;
|
|
-
|
|
- *endtag = oldchar, start = endtag;
|
|
- }
|
|
- } else if (!strcmp(start, "olddir")) {
|
|
- *endtag = oldchar, start = endtag;
|
|
-
|
|
- freeLogItem (oldDir);
|
|
-
|
|
- if (!(newlog->oldDir = readPath(configFile, lineNum,
|
|
- "olddir", &start))) {
|
|
- if (newlog != defConfig) {
|
|
- logerror = 1;
|
|
- continue;
|
|
- } else {
|
|
- goto error;
|
|
- }
|
|
- }
|
|
-#if 0
|
|
- if (stat(newlog->oldDir, &sb)) {
|
|
- message(MESS_ERROR, "%s:%d error verifying olddir "
|
|
- "path %s: %s\n", configFile, lineNum,
|
|
- newlog->oldDir, strerror(errno));
|
|
- free(newlog->oldDir);
|
|
- goto error;
|
|
- }
|
|
-
|
|
- if (!S_ISDIR(sb.st_mode)) {
|
|
- message(MESS_ERROR, "%s:%d olddir path %s is not a "
|
|
- "directory\n", configFile, lineNum,
|
|
- newlog->oldDir);
|
|
- free(newlog->oldDir);
|
|
- goto error;
|
|
- }
|
|
-#endif
|
|
-
|
|
- message(MESS_DEBUG, "olddir is now %s\n", newlog->oldDir);
|
|
- } else if (!strcmp(start, "extension")) {
|
|
- *endtag = oldchar, start = endtag;
|
|
-
|
|
- if (!isolateValue
|
|
- (configFile, lineNum, "extension name", &start,
|
|
- &endtag)) {
|
|
- oldchar = *endtag, *endtag = '\0';
|
|
-
|
|
- freeLogItem (extension);
|
|
- newlog->extension = strdup(start);
|
|
-
|
|
- *endtag = oldchar, start = endtag;
|
|
- }
|
|
-
|
|
- message(MESS_DEBUG, "extension is now %s\n",
|
|
- newlog->extension);
|
|
-
|
|
- } else if (!strcmp(start, "compresscmd")) {
|
|
- *endtag = oldchar, start = endtag;
|
|
-
|
|
- freeLogItem (compress_prog);
|
|
-
|
|
- if (!
|
|
- (newlog->compress_prog =
|
|
- readPath(configFile, lineNum, "compress", &start))) {
|
|
- if (newlog != defConfig) {
|
|
- logerror = 1;
|
|
- continue;
|
|
- } else {
|
|
- goto error;
|
|
- }
|
|
- }
|
|
-
|
|
- if (access(newlog->compress_prog, X_OK)) {
|
|
- message(MESS_ERROR,
|
|
- "%s:%d compression program %s is not an executable file\n",
|
|
- configFile, lineNum, newlog->compress_prog);
|
|
- if (newlog != defConfig) {
|
|
- logerror = 1;
|
|
- continue;
|
|
- } else {
|
|
- goto error;
|
|
- }
|
|
- }
|
|
-
|
|
- message(MESS_DEBUG, "compress_prog is now %s\n",
|
|
- newlog->compress_prog);
|
|
-
|
|
- } else if (!strcmp(start, "uncompresscmd")) {
|
|
- *endtag = oldchar, start = endtag;
|
|
-
|
|
- freeLogItem (uncompress_prog);
|
|
-
|
|
- if (!
|
|
- (newlog->uncompress_prog =
|
|
- readPath(configFile, lineNum, "uncompress",
|
|
- &start))) {
|
|
- if (newlog != defConfig) {
|
|
- logerror = 1;
|
|
- continue;
|
|
- } else {
|
|
- goto error;
|
|
- }
|
|
- }
|
|
-
|
|
- if (access(newlog->uncompress_prog, X_OK)) {
|
|
- message(MESS_ERROR,
|
|
- "%s:%d uncompression program %s is not an executable file\n",
|
|
- configFile, lineNum, newlog->uncompress_prog);
|
|
- if (newlog != defConfig) {
|
|
- logerror = 1;
|
|
- continue;
|
|
- } else {
|
|
- goto error;
|
|
- }
|
|
- }
|
|
-
|
|
- message(MESS_DEBUG, "uncompress_prog is now %s\n",
|
|
- newlog->uncompress_prog);
|
|
-
|
|
- } else if (!strcmp(start, "compressoptions")) {
|
|
- char *options;
|
|
-
|
|
- if (newlog->compress_options_list) {
|
|
- free(newlog->compress_options_list);
|
|
- newlog->compress_options_list = NULL;
|
|
- newlog->compress_options_count = 0;
|
|
- }
|
|
-
|
|
- *endtag = oldchar, start = endtag;
|
|
- if (!
|
|
- (options =
|
|
- readPath(configFile, lineNum, "compressoptions",
|
|
- &start))) {
|
|
- if (newlog != defConfig) {
|
|
- logerror = 1;
|
|
- continue;
|
|
- } else {
|
|
- goto error;
|
|
- }
|
|
- }
|
|
-
|
|
- if (poptParseArgvString(options,
|
|
- &newlog->compress_options_count,
|
|
- &newlog->compress_options_list)) {
|
|
- message(MESS_ERROR,
|
|
- "%s:%d invalid compression options\n",
|
|
- configFile, lineNum);
|
|
- free(options);
|
|
- if (newlog != defConfig) {
|
|
- logerror = 1;
|
|
- continue;
|
|
- } else {
|
|
- goto error;
|
|
- }
|
|
- }
|
|
-
|
|
- message(MESS_DEBUG, "compress_options is now %s\n",
|
|
- options);
|
|
- free(options);
|
|
- } else if (!strcmp(start, "compressext")) {
|
|
- *endtag = oldchar, start = endtag;
|
|
-
|
|
- freeLogItem (compress_ext);
|
|
-
|
|
- if (!
|
|
- (newlog->compress_ext =
|
|
- readPath(configFile, lineNum, "compress-ext",
|
|
- &start))) {
|
|
- if (newlog != defConfig) {
|
|
- logerror = 1;
|
|
- continue;
|
|
- } else {
|
|
- goto error;
|
|
- }
|
|
- }
|
|
-
|
|
- message(MESS_DEBUG, "compress_ext is now %s\n",
|
|
- newlog->compress_ext);
|
|
- } else {
|
|
- message(MESS_ERROR, "%s:%d unknown option '%s' "
|
|
- "-- ignoring line\n", configFile, lineNum, start);
|
|
-
|
|
- *endtag = oldchar, start = endtag;
|
|
- }
|
|
-
|
|
- while (isblank(*start))
|
|
- start++;
|
|
-
|
|
- if (*start != '\n') {
|
|
- message(MESS_ERROR, "%s:%d unexpected text\n", configFile,
|
|
- lineNum);
|
|
- while (*start != '\n')
|
|
- start++;
|
|
- }
|
|
-
|
|
- lineNum++;
|
|
- start++;
|
|
- } else if (*start == '/' || *start == '"' || *start == '\'') {
|
|
- if (newlog != defConfig) {
|
|
- message(MESS_ERROR, "%s:%d unexpected log filename\n",
|
|
- configFile, lineNum);
|
|
- logerror = 1;
|
|
- continue;
|
|
- }
|
|
-
|
|
- /* If no compression options were found in config file, set
|
|
- default values */
|
|
- if (!newlog->compress_prog)
|
|
- newlog->compress_prog = strdup(COMPRESS_COMMAND);
|
|
- if (!newlog->uncompress_prog)
|
|
- newlog->uncompress_prog = strdup(UNCOMPRESS_COMMAND);
|
|
- if (!newlog->compress_ext)
|
|
- newlog->compress_ext = strdup(COMPRESS_EXT);
|
|
-
|
|
- /* Allocate a new logInfo structure and insert it into the logs
|
|
- queue, copying the actual values from defConfig */
|
|
- if ((newlog = newLogInfo(defConfig)) == NULL)
|
|
- goto error;
|
|
-
|
|
- endtag = start;
|
|
- while (*endtag != '{' && *endtag != '\0')
|
|
- endtag++;
|
|
- if (*endtag != '{') {
|
|
- message(MESS_ERROR, "%s:%d missing end of line\n",
|
|
- configFile, lineNum);
|
|
- }
|
|
- *endtag = '\0';
|
|
-
|
|
- if (poptParseArgvString(start, &argc, &argv)) {
|
|
- message(MESS_ERROR, "%s:%d error parsing filename\n",
|
|
- configFile, lineNum);
|
|
- goto error;
|
|
- } else if (argc < 1) {
|
|
- message(MESS_ERROR,
|
|
- "%s:%d { expected after log file name(s)\n",
|
|
- configFile, lineNum);
|
|
- goto error;
|
|
- }
|
|
-
|
|
- newlog->files = NULL;
|
|
- newlog->numFiles = 0;
|
|
- for (argNum = 0; argNum < argc && logerror != 1; argNum++) {
|
|
- if (globerr_msg) {
|
|
- free(globerr_msg);
|
|
- globerr_msg = NULL;
|
|
- }
|
|
-
|
|
- rc = glob(argv[argNum], GLOB_NOCHECK, globerr,
|
|
- &globResult);
|
|
- if (rc == GLOB_ABORTED) {
|
|
- if (newlog->flags & LOG_FLAG_MISSINGOK)
|
|
- continue;
|
|
-
|
|
- /* We don't yet know whether this stanza has "missingok"
|
|
- * set, so store the error message for later. */
|
|
- rc = asprintf(&globerr_msg, "%s:%d glob failed for %s: %s\n",
|
|
- configFile, lineNum, argv[argNum], strerror(glob_errno));
|
|
- if (rc == -1)
|
|
- globerr_msg = NULL;
|
|
-
|
|
- globResult.gl_pathc = 0;
|
|
- }
|
|
-
|
|
- newlog->files =
|
|
- realloc(newlog->files,
|
|
- sizeof(*newlog->files) * (newlog->numFiles +
|
|
- globResult.
|
|
- gl_pathc));
|
|
-
|
|
- for (i = 0; i < globResult.gl_pathc; i++) {
|
|
- /* if we glob directories we can get false matches */
|
|
- if (!lstat(globResult.gl_pathv[i], &sb) &&
|
|
- S_ISDIR(sb.st_mode))
|
|
- continue;
|
|
-
|
|
- for (log = logs.tqh_first; log != NULL;
|
|
- log = log->list.tqe_next) {
|
|
- for (k = 0; k < log->numFiles; k++) {
|
|
- if (!strcmp(log->files[k],
|
|
- globResult.gl_pathv[i])) {
|
|
- message(MESS_ERROR,
|
|
- "%s:%d duplicate log entry for %s\n",
|
|
- configFile, lineNum,
|
|
- globResult.gl_pathv[i]);
|
|
- logerror = 1;
|
|
- goto duperror;
|
|
- }
|
|
+ break;
|
|
+ case STATE_SKIP_CONFIG:
|
|
+ if (*start == '}') {
|
|
+ state = STATE_DEFAULT;
|
|
+ freeTailLogs(1);
|
|
+ newlog = defConfig;
|
|
}
|
|
- }
|
|
-
|
|
- newlog->files[newlog->numFiles] =
|
|
- strdup(globResult.gl_pathv[i]);
|
|
- newlog->numFiles++;
|
|
- }
|
|
-duperror:
|
|
- globfree(&globResult);
|
|
- }
|
|
-
|
|
- newlog->pattern = strdup(start);
|
|
-
|
|
- if (!logerror)
|
|
- message(MESS_DEBUG, "reading config info for %s\n", start);
|
|
-
|
|
- free(argv);
|
|
-
|
|
- start = endtag + 1;
|
|
- } else if (*start == '}') {
|
|
- if (newlog == defConfig) {
|
|
- message(MESS_ERROR, "%s:%d unexpected }\n", configFile,
|
|
- lineNum);
|
|
- goto error;
|
|
- }
|
|
- if (globerr_msg) {
|
|
- if (!(newlog->flags & LOG_FLAG_MISSINGOK))
|
|
- message(MESS_ERROR, globerr_msg);
|
|
- free(globerr_msg);
|
|
- globerr_msg = NULL;
|
|
- if (!(newlog->flags & LOG_FLAG_MISSINGOK))
|
|
- return 1;
|
|
- }
|
|
-
|
|
- if (newlog->oldDir) {
|
|
- for (i = 0; i < newlog->numFiles; i++) {
|
|
- char *ld;
|
|
- dirName = ourDirName(newlog->files[i]);
|
|
- if (stat(dirName, &sb2)) {
|
|
- message(MESS_ERROR,
|
|
- "%s:%d error verifying log file "
|
|
- "path %s: %s\n", configFile, lineNum,
|
|
- dirName, strerror(errno));
|
|
- free(dirName);
|
|
- goto error;
|
|
- }
|
|
- ld = alloca(strlen(dirName) + strlen(newlog->oldDir) +
|
|
- 2);
|
|
- sprintf(ld, "%s/%s", dirName, newlog->oldDir);
|
|
- free(dirName);
|
|
-
|
|
- if (newlog->oldDir[0] != '/')
|
|
- dirName = ld;
|
|
- else
|
|
- dirName = newlog->oldDir;
|
|
- if (stat(dirName, &sb)) {
|
|
- message(MESS_ERROR, "%s:%d error verifying olddir "
|
|
- "path %s: %s\n", configFile, lineNum,
|
|
- dirName, strerror(errno));
|
|
- goto error;
|
|
- }
|
|
-
|
|
- if (sb.st_dev != sb2.st_dev) {
|
|
- message(MESS_ERROR,
|
|
- "%s:%d olddir %s and log file %s "
|
|
- "are on different devices\n", configFile,
|
|
- lineNum, newlog->oldDir, newlog->files[i]);
|
|
- goto error;
|
|
- }
|
|
- }
|
|
- }
|
|
-
|
|
- newlog = defConfig;
|
|
-
|
|
- start++;
|
|
- while (isblank(*start))
|
|
- start++;
|
|
-
|
|
- if (*start != '\n') {
|
|
- message(MESS_ERROR, "%s:%d, unexpected text after {\n",
|
|
- configFile, lineNum);
|
|
- }
|
|
- } else {
|
|
- message(MESS_ERROR, "%s:%d lines must begin with a keyword "
|
|
- "or a filename (possibly in double quotes)\n",
|
|
- configFile, lineNum);
|
|
-
|
|
- while (*start != '\n')
|
|
- start++;
|
|
+ else {
|
|
+ if ((key = isolateWord(&start, &buf, length)) == NULL)
|
|
+ continue;
|
|
+ if (
|
|
+ (strcmp(key, "postrotate") == 0) ||
|
|
+ (strcmp(key, "prerotate") == 0) ||
|
|
+ (strcmp(key, "firstrotate") == 0) ||
|
|
+ (strcmp(key, "lastrotate") == 0)
|
|
+ ) {
|
|
+ state = STATE_LOAD_SCRIPT | STATE_SKIP_CONFIG;
|
|
+ }
|
|
+ else {
|
|
+ state = STATE_SKIP_LINE | STATE_SKIP_CONFIG;
|
|
+ }
|
|
+ free(key);
|
|
+ key = NULL;
|
|
+ }
|
|
+ break;
|
|
+ }
|
|
+ if (key) {
|
|
+ free(key);
|
|
+ key = NULL;
|
|
+ }
|
|
+ if (*start == '\n') {
|
|
lineNum++;
|
|
- start++;
|
|
}
|
|
+
|
|
}
|
|
|
|
if (scriptStart) {
|
|
@@ -1521,11 +1455,14 @@
|
|
configFile);
|
|
goto error;
|
|
}
|
|
- munmap(buf, (size_t)(length + 2));
|
|
+
|
|
+ munmap(buf, (size_t) length);
|
|
close(fd);
|
|
return 0;
|
|
error:
|
|
- munmap(buf, (size_t)(length + 2));
|
|
+ if (key)
|
|
+ free(key);
|
|
+ munmap(buf, (size_t) length);
|
|
close(fd);
|
|
return 1;
|
|
}
|