Radix cross Linux

The main Radix cross Linux repository contains the build scripts of packages, which have the most complete and common functionality for desktop machines

452 Commits   2 Branches   1 Tag
Index: Makefile
===================================================================
--- Makefile	(nonexistent)
+++ Makefile	(revision 5)
@@ -0,0 +1,56 @@
+
+COMPONENT_TARGETS = $(HARDWARE_NOARCH)
+
+
+include ../../../../build-system/constants.mk
+
+
+url         = $(DOWNLOAD_SERVER)/sources/packages/a/logrotate
+
+versions    = 3.18.0
+pkgname     = logrotate
+suffix      = tar.xz
+
+tarballs    = $(addsuffix .$(suffix), $(addprefix $(pkgname)-, $(versions)))
+sha1s       = $(addsuffix .sha1sum, $(tarballs))
+
+patches     = $(CURDIR)/patches/logrotate-3.18.0.patch
+
+.NOTPARALLEL: $(patches)
+
+
+BUILD_TARGETS = $(tarballs) $(sha1s) $(patches)
+
+
+include ../../../../build-system/core.mk
+
+
+.PHONY: download_clean
+
+
+$(tarballs):
+	@echo -e "\n======= Downloading source tarballs =======" ; \
+	 for tarball in $(tarballs) ; do \
+	   echo "$(url)/$$tarball" | xargs -n 1 -P 100 wget $(WGET_OPTIONS) - & \
+	 done ; wait
+
+$(sha1s): $(tarballs)
+	@for sha in $@ ; do \
+	   echo -e "\n======= Downloading '$$sha' signature =======\n" ; \
+	   echo "$(url)/$$sha" | xargs -n 1 -P 100 wget $(WGET_OPTIONS) - & wait %1 ; \
+	   touch $$sha ; \
+	   echo -e "\n======= Check the '$$sha' sha1sum =======\n" ; \
+	   sha1sum --check $$sha ; ret="$$?" ; \
+	   if [ "$$ret" == "1" ]; then \
+	     echo -e "\n======= ERROR: Bad '$$sha' sha1sum =======\n" ; \
+	     exit 1 ; \
+	   fi ; \
+	 done
+
+$(patches): $(sha1s)
+	@echo -e "\n======= Create Patches =======\n" ; \
+	 ( cd create-3.18.0-patch ; ./create.patch.sh ) ; \
+	 echo -e "\n"
+
+download_clean:
+	@rm -f $(tarballs) $(sha1s) $(patches)
Index: create-3.18.0-patch/create.patch.sh
===================================================================
--- create-3.18.0-patch/create.patch.sh	(nonexistent)
+++ create-3.18.0-patch/create.patch.sh	(revision 5)
@@ -0,0 +1,15 @@
+#!/bin/sh
+
+VERSION=3.18.0
+
+tar --files-from=file.list -xJvf ../logrotate-$VERSION.tar.xz
+mv logrotate-$VERSION logrotate-$VERSION-orig
+
+cp -rf ./logrotate-$VERSION-new ./logrotate-$VERSION
+
+diff --unified -Nr  logrotate-$VERSION-orig logrotate-$VERSION > logrotate-$VERSION.patch
+
+mv logrotate-$VERSION.patch ../patches
+
+rm -rf ./logrotate-$VERSION
+rm -rf ./logrotate-$VERSION-orig

Property changes on: create-3.18.0-patch/create.patch.sh
___________________________________________________________________
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: create-3.18.0-patch/file.list
===================================================================
--- create-3.18.0-patch/file.list	(nonexistent)
+++ create-3.18.0-patch/file.list	(revision 5)
@@ -0,0 +1,2 @@
+logrotate-3.18.0/config.c
+logrotate-3.18.0/logrotate.8.in
Index: create-3.18.0-patch/logrotate-3.18.0-new/config.c
===================================================================
--- create-3.18.0-patch/logrotate-3.18.0-new/config.c	(nonexistent)
+++ create-3.18.0-patch/logrotate-3.18.0-new/config.c	(revision 5)
@@ -0,0 +1,2109 @@
+#include "queue.h"
+#include <limits.h>
+#include <ctype.h>
+#include <dirent.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <glob.h>
+#include <grp.h>
+#include <popt.h>
+#include <pwd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <time.h>
+#include <unistd.h>
+#include <assert.h>
+#include <wchar.h>
+#include <wctype.h>
+#include <fnmatch.h>
+#include <sys/mman.h>
+#include <libgen.h>
+
+#if !defined(PATH_MAX) && defined(__FreeBSD__)
+#include <sys/param.h>
+#endif
+
+#include "log.h"
+#include "logrotate.h"
+
+struct logInfoHead logs;
+
+#if !defined(GLOB_ABORTED) && defined(GLOB_ABEND)
+#define GLOB_ABORTED GLOB_ABEND
+#endif
+
+#define REALLOC_STEP            10
+#define GLOB_STR_REALLOC_STEP   0x100
+
+#if defined(SunOS) && !defined(isblank)
+#define isblank(c) ( ( (c) == ' ' || (c) == '\t' ) ? 1 : 0 )
+#endif
+
+#ifdef __hpux
+#include "asprintf.c"
+#endif
+
+#if !defined(HAVE_SECURE_GETENV)
+#define secure_getenv getenv
+#endif
+
+#if !defined(HAVE_ASPRINTF) && !defined(_FORTIFY_SOURCE)
+#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_end(arg);
+    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.
+         */
+        message_OOM();
+        exit(1);
+    }
+    rv = vsnprintf(str, size, format, arg);
+    va_end(arg);
+
+    *string_ptr = str;
+    return (rv);
+}
+
+#endif
+
+#if !defined(HAVE_STRNDUP)
+char *strndup(const char *s, size_t n)
+{
+    size_t nAvail;
+    char *p;
+
+    /* min() */
+    nAvail = strlen(s) + 1;
+    if ( (n + 1) < nAvail)
+        nAvail = n + 1;
+
+    p = malloc(nAvail);
+    if (!p)
+        return NULL;
+    memcpy(p, s, nAvail);
+    p[nAvail - 1] = 0;
+    return p;
+}
+#endif
+
+/* list of compression commands and the corresponding file extensions */
+struct compress_cmd_item {
+    const char *cmd;
+    const char *ext;
+};
+static const struct compress_cmd_item compress_cmd_list[] = {
+    {"gzip", ".gz"},
+    {"bzip2", ".bz2"},
+    {"xz", ".xz"},
+    {"zstd", ".zst"},
+    {"compress", ".Z"},
+    {"zip", "zip"},
+};
+static const unsigned compress_cmd_list_size = sizeof(compress_cmd_list)
+    / sizeof(compress_cmd_list[0]);
+
+enum {
+    STATE_DEFAULT = 2,
+    STATE_SKIP_LINE = 4,
+    STATE_DEFINITION_END = 8,
+    STATE_SKIP_CONFIG = 16,
+    STATE_LOAD_SCRIPT = 32,
+    STATE_ERROR = 64,
+};
+
+static const char *defTabooExts[] = {
+    ",v",
+    ".bak",
+    ".cfsaved",
+    ".disabled",
+    ".dpkg-bak",
+    ".dpkg-del",
+    ".dpkg-dist",
+    ".dpkg-new",
+    ".dpkg-old",
+    ".dpkg-tmp",
+    ".rhn-cfg-tmp-*",
+    ".rpmnew",
+    ".rpmorig",
+    ".rpmsave",
+    ".swp",
+    ".ucf-dist",
+    ".ucf-new",
+    ".ucf-old",
+    ".new",
+    ".old",
+    ".orig",
+    ".bak",
+    "~"
+};
+static const unsigned defTabooCount = sizeof(defTabooExts) / sizeof(char *);
+
+/* I shouldn't use globals here :-( */
+static char **tabooPatterns = NULL;
+static unsigned tabooCount = 0;
+static int glob_errno = 0;
+
+static int readConfigFile(const char *configFile, struct logInfo *defConfig);
+static int globerr(const char *pathname, int theerr);
+
+static char *isolateLine(char **strt, char **buf, size_t length) {
+    char *endtag, *start, *tmp;
+    const char *max = *buf + length;
+    char *key;
+
+    start = *strt;
+    endtag = start;
+    while (endtag < max && *endtag != '\n') {
+        endtag++;}
+    if (max < endtag)
+        return NULL;
+    tmp = endtag - 1;
+    while (isspace((unsigned char)*endtag))
+        endtag--;
+    key = strndup(start, (size_t)(endtag - start + 1));
+    if (key == NULL) {
+        message_OOM();
+        return NULL;
+    }
+    *strt = tmp;
+    return key;
+}
+
+static char *isolateValue(const char *fileName, int lineNum, const char *key,
+                          char **startPtr, char **buf, size_t length)
+{
+    char *chptr = *startPtr;
+    const char *max = *startPtr + length;
+
+    while (chptr < max && isblank((unsigned char)*chptr))
+        chptr++;
+    if (chptr < max && *chptr == '=') {
+        chptr++;
+        while ( chptr < max && isblank((unsigned char)*chptr))
+            chptr++;
+    }
+
+    if (chptr < max && *chptr == '\n') {
+        message(MESS_ERROR, "%s:%d argument expected after %s\n",
+                fileName, lineNum, key);
+        return NULL;
+    }
+
+    *startPtr = chptr;
+    return isolateLine(startPtr, buf, length);
+}
+
+static char *isolateWord(char **strt, char **buf, size_t length) {
+    char *endtag, *start;
+    const char *max = *buf + length;
+    char *key;
+    start = *strt;
+    while (start < max && isblank((unsigned char)*start))
+        start++;
+    endtag = start;
+    while (endtag < max && isalpha((unsigned char)*endtag)) {
+        endtag++;}
+    if (max < endtag)
+        return NULL;
+    key = strndup(start, (size_t)(endtag - start));
+    if (key == NULL) {
+        message_OOM();
+        return NULL;
+    }
+    *strt = endtag;
+    return key;
+}
+
+static char *readPath(const char *configFile, int lineNum, const char *key,
+                      char **startPtr, char **buf, size_t length)
+{
+    char *path = isolateValue(configFile, lineNum, key, startPtr, buf, length);
+    if (path != NULL) {
+        wchar_t pwc;
+        size_t len;
+        const char *chptr = path;
+
+        while (*chptr && (len = mbrtowc(&pwc, chptr, strlen(chptr), NULL)) != 0) {
+            if (len == (size_t)(-1) || len == (size_t)(-2) || !iswprint((wint_t)pwc) || iswblank((wint_t)pwc)) {
+                message(MESS_ERROR, "%s:%d bad %s path %s\n",
+                        configFile, lineNum, key, path);
+                free(path);
+                return NULL;
+            }
+            chptr += len;
+        }
+    }
+    return path;
+}
+
+/* set *pUid to UID of the given user, return non-zero on failure */
+static int resolveUid(const char *userName, uid_t *pUid)
+{
+    const struct passwd *pw;
+    char *endptr;
+    unsigned long int parsed_uid;
+
+#ifdef __CYGWIN__
+    if (strcmp(userName, "root") == 0) {
+        *pUid = 0;
+        return 0;
+    }
+#endif
+
+    pw = getpwnam(userName);
+    if (pw) {
+        *pUid = pw->pw_uid;
+        return 0;
+    }
+
+    parsed_uid = strtoul(userName, &endptr, 10);
+    if (userName[0] != '\0' &&
+        *endptr == '\0' &&
+        parsed_uid < INT_MAX && /* parsed_uid != ULONG_MAX && */
+        getpwuid((uid_t)parsed_uid) != NULL) {
+
+        *pUid = (uid_t)parsed_uid;
+        return 0;
+    }
+
+    return -1;
+}
+
+/* set *pGid to GID of the given group, return non-zero on failure */
+static int resolveGid(const char *groupName, gid_t *pGid)
+{
+    const struct group *gr;
+    char *endptr;
+    unsigned long int parsed_gid;
+
+#ifdef __CYGWIN__
+    if (strcmp(groupName, "root") == 0) {
+        *pGid = 0;
+        return 0;
+    }
+#endif
+
+    gr = getgrnam(groupName);
+    if (gr) {
+        *pGid = gr->gr_gid;
+        return 0;
+    }
+
+    parsed_gid = strtoul(groupName, &endptr, 10);
+    if (groupName[0] != '\0' &&
+        *endptr == '\0' &&
+        parsed_gid < INT_MAX && /* parsed_gid != ULONG_MAX && */
+        getgrgid((gid_t)parsed_gid) != NULL) {
+
+        *pGid = (gid_t)parsed_gid;
+        return 0;
+    }
+
+    return -1;
+}
+
+static int readModeUidGid(const char *configFile, int lineNum, char *key,
+                          const char *directive, mode_t *mode, uid_t *pUid,
+                          gid_t *pGid)
+{
+    char u[200], g[200];
+    mode_t m = 0;
+    char tmp;
+    int rc;
+
+    if (!strcmp("su", directive))
+        /* do not read <mode> for the 'su' directive */
+        rc = 0;
+    else {
+        unsigned short int parsed_mode;
+        rc = sscanf(key, "%ho %199s %199s%c", &parsed_mode, u, g, &tmp);
+        m = parsed_mode;
+    }
+
+    /* We support 'key <owner> <group> notation now */
+    if (rc == 0) {
+        rc = sscanf(key, "%199s %199s%c", u, g, &tmp);
+        /* Simulate that we have read mode and keep the default value. */
+        if (rc > 0) {
+            m = *mode;
+            rc += 1;
+        }
+    }
+
+    if (rc == 4) {
+        message(MESS_ERROR, "%s:%d extra arguments for "
+                "%s\n", configFile, lineNum, directive);
+        return -1;
+    }
+
+    if (rc > 0) {
+        *mode = m;
+    }
+
+    if (rc > 1) {
+        if (resolveUid(u, pUid) != 0) {
+            message(MESS_ERROR, "%s:%d unknown user '%s'\n",
+                    configFile, lineNum, u);
+            return -1;
+        }
+    }
+    if (rc > 2) {
+        if (resolveGid(g, pGid) != 0) {
+            message(MESS_ERROR, "%s:%d unknown group '%s'\n",
+                    configFile, lineNum, g);
+            return -1;
+        }
+    }
+
+    return 0;
+}
+
+static char *readAddress(const char *configFile, int lineNum, const char *key,
+                         char **startPtr, char **buf, size_t length)
+{
+    char *start = *startPtr;
+    char *address = isolateValue(configFile, lineNum, key, startPtr, buf, length);
+
+    if (address != NULL) {
+        /* validate the address */
+        const char *chptr = address;
+        while (isprint((unsigned char) *chptr) && *chptr != ' ') {
+            chptr++;
+        }
+
+        if (*chptr) {
+            message(MESS_ERROR, "%s:%d bad %s address %s\n",
+                    configFile, lineNum, key, start);
+            free(address);
+            return NULL;
+        }
+    }
+
+    return address;
+}
+
+static int do_mkdir(const char *path, mode_t mode, uid_t uid, gid_t gid) {
+    if (mkdir(path, mode) == 0) {
+        /* newly created directory, set the owner and permissions */
+        if (chown(path, uid, gid) != 0) {
+            message(MESS_ERROR, "error setting owner of %s to uid %u and gid %u: %s\n",
+                    path, (unsigned) uid, (unsigned) gid, strerror(errno));
+            return -1;
+        }
+
+        if (chmod(path, mode) != 0) {
+            message(MESS_ERROR, "error setting permissions of %s to 0%o: %s\n",
+                    path, mode, strerror(errno));
+            return -1;
+        }
+
+        return 0;
+    }
+
+    if (errno == EEXIST) {
+        /* path already exists, check whether it is a directory or not */
+        struct stat sb;
+        if ((stat(path, &sb) == 0) && S_ISDIR(sb.st_mode))
+            return 0;
+
+        message(MESS_ERROR, "path %s already exists, but it is not a directory\n", path);
+        errno = ENOTDIR;
+        return -1;
+    }
+
+    message(MESS_ERROR, "error creating %s: %s\n", path, strerror(errno));
+    return -1;
+}
+
+static int mkpath(const char *path, mode_t mode, uid_t uid, gid_t gid) {
+    char *pp;
+    char *sp;
+    int rv;
+    char *copypath = strdup(path);
+
+    if (!copypath) {
+        message_OOM();
+        return 1;
+    }
+
+    rv = 0;
+    pp = copypath;
+    while (rv == 0 && (sp = strchr(pp, '/')) != NULL) {
+        if (sp != pp) {
+            *sp = '\0';
+            rv = do_mkdir(copypath, mode, uid, gid);
+            *sp = '/';
+        }
+        pp = sp + 1;
+    }
+    if (rv == 0) {
+        rv = do_mkdir(path, mode, uid, gid);
+    }
+    free(copypath);
+    return rv;
+}
+
+static int checkFile(const char *fname)
+{
+    unsigned i;
+
+    /* Check if fname is '.' or '..'; if so, return false */
+    if (fname[0] == '.' && (!fname[1] || (fname[1] == '.' && !fname[2])))
+        return 0;
+
+    /* Check if fname is ending in a taboo-extension; if so, return false */
+    for (i = 0; i < tabooCount; i++) {
+        const char *pattern = tabooPatterns[i];
+        if (!fnmatch(pattern, fname, FNM_PERIOD))
+        {
+            message(MESS_DEBUG, "Ignoring %s, because of %s pattern match\n",
+                    fname, pattern);
+            return 0;
+        }
+    }
+    /* All checks have been passed; return true */
+    return 1;
+}
+
+/* Used by qsort to sort filelist */
+static int compar(const void *p, const void *q)
+{
+    return strcoll(*((char * const*) p), *((char * const*) q));
+}
+
+/* Free memory blocks pointed to by pointers in a 2d array and the array itself */
+static void free_2d_array(char **array, unsigned lines_count)
+{
+    unsigned i;
+    for (i = 0; i < lines_count; ++i)
+        free(array[i]);
+    free(array);
+}
+
+#define MEMBER_COPY(dest, src) \
+    do { \
+        if ((src) && rv == 0) { \
+            (dest) = strdup(src); \
+            if ((dest) == NULL) { \
+                message_OOM(); \
+                rv = 1; \
+            } \
+        } else { \
+            (dest) = NULL; \
+        } \
+    } while (0)
+static int copyLogInfo(struct logInfo *to, const struct logInfo *from)
+{
+    int rv = 0;
+
+    memset(to, 0, sizeof(*to));
+    MEMBER_COPY(to->oldDir, from->oldDir);
+    to->criterium = from->criterium;
+    to->weekday = from->weekday;
+    to->threshold = from->threshold;
+    to->minsize = from->minsize;
+    to->maxsize = from->maxsize;
+    to->rotateCount = from->rotateCount;
+    to->rotateMinAge = from->rotateMinAge;
+    to->rotateAge = from->rotateAge;
+    to->logStart = from->logStart;
+    MEMBER_COPY(to->pre, from->pre);
+    MEMBER_COPY(to->post, from->post);
+    MEMBER_COPY(to->first, from->first);
+    MEMBER_COPY(to->last, from->last);
+    MEMBER_COPY(to->preremove, from->preremove);
+    MEMBER_COPY(to->logAddress , from->logAddress);
+    MEMBER_COPY(to->extension, from->extension);
+    MEMBER_COPY(to->compress_prog, from->compress_prog);
+    MEMBER_COPY(to->uncompress_prog, from->uncompress_prog);
+    MEMBER_COPY(to->compress_ext, from->compress_ext);
+    to->flags = from->flags;
+    to->shred_cycles = from->shred_cycles;
+    to->createMode = from->createMode;
+    to->createUid = from->createUid;
+    to->createGid = from->createGid;
+    to->suUid = from->suUid;
+    to->suGid = from->suGid;
+    to->olddirMode = from->olddirMode;
+    to->olddirUid = from->olddirUid;
+    to->olddirGid = from->olddirGid;
+
+    if (from->compress_options_count) {
+        poptDupArgv(from->compress_options_count, from->compress_options_list,
+                    &to->compress_options_count,  &to->compress_options_list);
+        if (to->compress_options_list == NULL) {
+            message_OOM();
+            rv = 1;
+        }
+    }
+
+    MEMBER_COPY(to->dateformat, from->dateformat);
+
+    to->list = from->list;
+
+    return rv;
+}
+#undef MEMBER_COPY
+
+static void freeLogInfo(struct logInfo *log)
+{
+    free(log->pattern);
+    free_2d_array(log->files, log->numFiles);
+    free(log->oldDir);
+    free(log->pre);
+    free(log->post);
+    free(log->first);
+    free(log->last);
+    free(log->preremove);
+    free(log->logAddress);
+    free(log->extension);
+    free(log->compress_prog);
+    free(log->uncompress_prog);
+    free(log->compress_ext);
+    free(log->compress_options_list);
+    free(log->dateformat);
+}
+
+static struct logInfo *newLogInfo(const struct logInfo *template)
+{
+    struct logInfo *new;
+
+    new = malloc(sizeof(*new));
+    if (new == NULL) {
+        message_OOM();
+        return NULL;
+    }
+
+    if (copyLogInfo(new, template)) {
+        freeLogInfo(new);
+        free(new);
+        return NULL;
+    }
+
+    TAILQ_INSERT_TAIL(&logs, new, list);
+    numLogs++;
+
+    return new;
+}
+
+static void removeLogInfo(struct logInfo *log)
+{
+    if (log == NULL)
+        return;
+
+    freeLogInfo(log);
+    TAILQ_REMOVE(&logs, log, list);
+    free(log);
+    numLogs--;
+}
+
+static void freeTailLogs(int num)
+{
+    message(MESS_DEBUG, "removing last %d log configs\n", num);
+
+    while (num--)
+        removeLogInfo(TAILQ_LAST(&logs, logInfoHead));
+
+}
+
+static const char *crit_to_string(enum criterium crit)
+{
+    switch (crit) {
+        case ROT_HOURLY:    return "hourly";
+        case ROT_DAYS:      return "daily";
+        case ROT_WEEKLY:    return "weekly";
+        case ROT_MONTHLY:   return "monthly";
+        case ROT_YEARLY:    return "yearly";
+        case ROT_SIZE:      return "size";
+        default:            return "XXX";
+    }
+}
+
+static void set_criterium(enum criterium *pDst, enum criterium src, int *pSet)
+{
+    if (*pSet && (*pDst != src)) {
+        /* we are overriding a previously set criterium */
+        message(MESS_VERBOSE, "warning: '%s' overrides previously specified '%s'\n",
+                crit_to_string(src), crit_to_string(*pDst));
+    }
+    *pDst = src;
+    *pSet = 1;
+}
+
+static int readConfigPath(const char *path, struct logInfo *defConfig)
+{
+    struct stat sb;
+    int result = 0;
+    struct logInfo defConfigBackup;
+
+    if (stat(path, &sb)) {
+        message(MESS_ERROR, "cannot stat %s: %s\n", path, strerror(errno));
+        return 1;
+    }
+
+    if (S_ISDIR(sb.st_mode)) {
+        char **namelist = NULL;
+        struct dirent *dp;
+        int here;
+        unsigned files_count = 0, i;
+        DIR *dirp;
+
+        if ((here = open(".", O_RDONLY)) == -1) {
+            message(MESS_ERROR, "cannot open current directory: %s\n",
+                    strerror(errno));
+            return 1;
+        }
+
+        if ((dirp = opendir(path)) == NULL) {
+            message(MESS_ERROR, "cannot open directory %s: %s\n", path,
+                    strerror(errno));
+            close(here);
+            return 1;
+        }
+        while ((dp = readdir(dirp)) != NULL) {
+            if (checkFile(dp->d_name)) {
+                /* Realloc memory for namelist array if necessary */
+                if (files_count % REALLOC_STEP == 0) {
+                    char **p = (char **) realloc(namelist,
+                            (files_count +
+                             REALLOC_STEP) * sizeof(char *));
+                    if (p) {
+                        namelist = p;
+                        memset(namelist + files_count, '\0',
+                               REALLOC_STEP * sizeof(char *));
+                    } else {
+                        free_2d_array(namelist, files_count);
+                        closedir(dirp);
+                        close(here);
+                        message_OOM();
+                        return 1;
+                    }
+                }
+                /* Alloc memory for file name */
+                namelist[files_count] = strdup(dp->d_name);
+                if (namelist[files_count] != NULL) {
+                    files_count++;
+                } else {
+                    free_2d_array(namelist, files_count);
+                    closedir(dirp);
+                    close(here);
+                    message_OOM();
+                    return 1;
+                }
+            }
+        }
+        closedir(dirp);
+
+        if (files_count > 0) {
+            qsort(namelist, files_count, sizeof(char *), compar);
+        } else {
+            close(here);
+            return 0;
+        }
+
+        if (chdir(path)) {
+            message(MESS_ERROR, "error in chdir(\"%s\"): %s\n", path,
+                    strerror(errno));
+            close(here);
+            free_2d_array(namelist, files_count);
+            return 1;
+        }
+
+        for (i = 0; i < files_count; ++i) {
+            assert(namelist[i] != NULL);
+            if (copyLogInfo(&defConfigBackup, defConfig)) {
+                freeLogInfo(&defConfigBackup);
+                close(here);
+                free_2d_array(namelist, files_count);
+                return 1;
+            }
+            if (readConfigFile(namelist[i], defConfig)) {
+                message(MESS_ERROR, "found error in file %s, skipping\n", namelist[i]);
+                freeLogInfo(defConfig);
+                if (copyLogInfo(defConfig, &defConfigBackup)){} /* do not check, we are already in a error path */
+                freeLogInfo(&defConfigBackup);
+                result = 1;
+                continue;
+            }
+            freeLogInfo(&defConfigBackup);
+        }
+
+        if (fchdir(here) < 0) {
+            message(MESS_ERROR, "could not change directory to '.': %s\n", strerror(errno));
+        }
+        close(here);
+        free_2d_array(namelist, files_count);
+    } else {
+        if (copyLogInfo(&defConfigBackup, defConfig)) {
+            freeLogInfo(&defConfigBackup);
+            return 1;
+        }
+
+        if (readConfigFile(path, defConfig)) {
+            freeLogInfo(defConfig);
+            if (copyLogInfo(defConfig, &defConfigBackup)){} /* do not check, we are already in a error path */
+            result = 1;
+        }
+        freeLogInfo(&defConfigBackup);
+    }
+
+    return result;
+}
+
+int readAllConfigPaths(const char **paths)
+{
+    int result = 0;
+    unsigned i;
+    const char **file;
+    struct logInfo defConfig = {
+        .pattern = NULL,
+        .files = NULL,
+        .numFiles = 0,
+        .oldDir = NULL,
+        .criterium = ROT_SIZE,
+        .threshold = 1024 * 1024,
+        .minsize = 0,
+        .maxsize = 0,
+        .rotateCount = 0,
+        .rotateMinAge = 0,
+        .rotateAge = 0,
+        .logStart = -1,
+        .pre = NULL,
+        .post = NULL,
+        .first = NULL,
+        .last = NULL,
+        .preremove = NULL,
+        .logAddress = NULL,
+        .extension = NULL,
+        .addextension = NULL,
+        .compress_prog = NULL,
+        .uncompress_prog = NULL,
+        .compress_ext = NULL,
+        .dateformat = NULL,
+        .flags = LOG_FLAG_IFEMPTY,
+        .shred_cycles = 0,
+        .createMode = NO_MODE,
+        .createUid = NO_UID,
+        .createGid = NO_GID,
+        .olddirMode = NO_MODE,
+        .olddirUid = NO_UID,
+        .olddirGid = NO_GID,
+        .suUid = NO_UID,
+        .suGid = NO_GID,
+        .compress_options_list = NULL,
+        .compress_options_count = 0
+    };
+
+    tabooPatterns = malloc(sizeof(*tabooPatterns) * defTabooCount);
+    if (tabooPatterns == NULL) {
+        message_OOM();
+        return 1;
+    }
+
+
+    for (i = 0; i < defTabooCount; i++) {
+        int bytes;
+        char *pattern = NULL;
+
+        /* generate a pattern by concatenating star (wildcard) to the
+         * suffix literal
+         */
+        bytes = asprintf(&pattern, "*%s", defTabooExts[i]);
+        if (bytes != -1) {
+            tabooPatterns[i] = pattern;
+            tabooCount++;
+        } else {
+            free_2d_array(tabooPatterns, tabooCount);
+            message_OOM();
+            return 1;
+        }
+    }
+
+    for (file = paths; *file; file++) {
+        if (readConfigPath(*file, &defConfig))
+            result = 1;
+    }
+    free_2d_array(tabooPatterns, tabooCount);
+    freeLogInfo(&defConfig);
+    return result;
+}
+
+static char* parseGlobString(const char *configFile, int lineNum,
+                             const char *buf, size_t length, char **ppos)
+{
+    /* output buffer */
+    char *globString = NULL;
+    size_t globStringPos = 0;
+    size_t globStringAlloc = 0;
+    enum {
+        PGS_INIT,   /* picking blanks, looking for '#' */
+        PGS_DATA,   /* picking data, looking for end of line */
+        PGS_COMMENT /* skipping comment, looking for end of line */
+    } state = PGS_INIT;
+
+    /* move the cursor at caller's side while going through the input */
+    for (; ((size_t)(*ppos - buf) < length) && **ppos; (*ppos)++) {
+        /* state transition (see above) */
+        switch (state) {
+            case PGS_INIT:
+                if ('#' == **ppos)
+                    state = PGS_COMMENT;
+                else if (!isspace((unsigned char) **ppos))
+                    state = PGS_DATA;
+                break;
+
+            default:
+                if ('\n' == **ppos)
+                    state = PGS_INIT;
+        }
+
+        if (PGS_COMMENT == state)
+            /* skip comment */
+            continue;
+
+        switch (**ppos) {
+            case '}':
+                message(MESS_ERROR, "%s:%d unexpected } (missing previous '{')\n", configFile, lineNum);
+                free(globString);
+                return NULL;
+
+            case '{':
+                /* NUL-terminate globString */
+                assert(globStringPos < globStringAlloc);
+                globString[globStringPos] = '\0';
+                return globString;
+
+            default:
+                break;
+        }
+
+        /* grow the output buffer if needed */
+        if (globStringPos + 2 > globStringAlloc) {
+            char *ptr;
+            globStringAlloc += GLOB_STR_REALLOC_STEP;
+            ptr = realloc(globString, globStringAlloc);
+            if (!ptr) {
+                message_OOM();
+                free(globString);
+                return NULL;
+            }
+            globString = ptr;
+        }
+
+        /* copy a single character */
+        globString[globStringPos++] = **ppos;
+    }
+
+    /* premature end of input */
+    message(MESS_ERROR, "%s:%d missing '{' after log files definition\n", configFile, lineNum);
+    free(globString);
+    return NULL;
+}
+
+static int globerr(const char *pathname, int theerr)
+{
+    (void) pathname;
+
+    /* prevent glob() from being aborted in certain cases */
+    switch (theerr) {
+        case ENOTDIR:
+            /* non-directory where directory was expected by the glob */
+            return 0;
+
+        case ENOENT:
+            /* most likely symlink with non-existent target */
+            return 0;
+
+        default:
+            break;
+    }
+
+    glob_errno = theerr;
+
+    /* We want the glob operation to abort on error, so return 1 */
+    return 1;
+}
+
+#define freeLogItem(what) \
+    do { \
+        free(newlog->what); \
+        newlog->what = NULL; \
+    } while (0)
+#define RAISE_ERROR() \
+    if (newlog != defConfig) { \
+        state = STATE_ERROR; \
+        goto next_state; \
+    } else { \
+        goto error; \
+    }
+#define MAX_NESTING 16U
+
+static int readConfigFile(const char *configFile, struct logInfo *defConfig)
+{
+    int fd;
+    char *buf, *key = NULL;
+    size_t length;
+    int lineNum = 1;
+    char *scriptStart = NULL;
+    char **scriptDest = NULL;
+    struct logInfo *newlog = defConfig;
+    char *start, *chptr;
+    struct stat sb;
+    int state = STATE_DEFAULT;
+    int logerror = 0;
+    /* to check if incompatible criteria are specified */
+    int criterium_set = 0;
+    static unsigned recursion_depth = 0U;
+    char *globerr_msg = NULL;
+    int in_config = 0;
+    struct flock fd_lock = {
+        .l_start = 0,
+        .l_len = 0,
+        .l_whence = SEEK_SET,
+        .l_type = F_RDLCK
+    };
+
+    fd = open(configFile, O_RDONLY);
+    if (fd < 0) {
+        message(MESS_ERROR, "failed to open config file %s: %s\n",
+                configFile, strerror(errno));
+        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);
+    }
+    if (fstat(fd, &sb)) {
+        message(MESS_ERROR, "fstat of %s failed: %s\n", configFile,
+                strerror(errno));
+        close(fd);
+        return 1;
+    }
+    if (!S_ISREG(sb.st_mode)) {
+        message(MESS_DEBUG,
+                "Ignoring %s because it's not a regular file.\n",
+                configFile);
+        close(fd);
+        return 0;
+    }
+
+    if (!getpwuid(getuid())) {
+        message(MESS_ERROR, "Cannot find logrotate UID (%d) in passwd file: %s\n",
+                getuid(), strerror(errno));
+        close(fd);
+        return 1;
+    }
+
+    if (getuid() == ROOT_UID) {
+        if ((sb.st_mode & 07533) != 0400) {
+            message(MESS_DEBUG,
+                    "Potentially dangerous mode on %s: 0%o\n",
+                    configFile, (unsigned) (sb.st_mode & 07777));
+        }
+
+        if (sb.st_mode & 0022) {
+            message(MESS_ERROR,
+                    "Ignoring %s because it is writable by group or others.\n",
+                    configFile);
+            close(fd);
+            return 0;
+        }
+
+        if (sb.st_uid != ROOT_UID) {
+            message(MESS_ERROR,
+                    "Ignoring %s because the file owner is wrong (should be root or user with uid 0).\n",
+                    configFile);
+            close(fd);
+            return 0;
+        }
+    }
+
+    length = (size_t)sb.st_size;
+
+    if (length > 0xffffff) {
+        message(MESS_ERROR, "file %s too large, probably not a config file.\n",
+                configFile);
+        close(fd);
+        return 1;
+    }
+
+    /* 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, length, PROT_READ,
+            MAP_PRIVATE | MAP_POPULATE, fd, (off_t) 0);
+#else /* MAP_POPULATE */
+    buf = mmap(NULL, 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));
+        close(fd);
+        return 1;
+    }
+
+#ifdef HAVE_MADVISE
+#ifdef MADV_DONTFORK
+    madvise(buf, length + 2,
+            MADV_SEQUENTIAL | MADV_WILLNEED | MADV_DONTFORK);
+#else /* MADV_DONTFORK */
+    madvise(buf, length + 2,
+            MADV_SEQUENTIAL | MADV_WILLNEED);
+#endif /* MADV_DONTFORK */
+#endif /* HAVE_MADVISE */
+
+    message(MESS_DEBUG, "reading config file %s\n", configFile);
+
+    for (start = buf; (size_t)(start - buf) < length; start++) {
+        switch (state) {
+            case STATE_DEFAULT:
+                if (isblank((unsigned char)*start))
+                    continue;
+                /* Skip comment */
+                if (*start == '#') {
+                    state = STATE_SKIP_LINE;
+                    continue;
+                }
+
+                if (isalpha((unsigned char)*start)) {
+                    free(key);
+                    key = isolateWord(&start, &buf, length);
+                    if (key == 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, "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, "renamecopy")) {
+                        newlog->flags |= LOG_FLAG_TMPFILENAME;
+                    } else if (!strcmp(key, "norenamecopy")) {
+                        newlog->flags &= ~LOG_FLAG_TMPFILENAME;
+                    } 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, "dateyesterday")) {
+                        newlog->flags |= LOG_FLAG_DATEYESTERDAY;
+                    } else if (!strcmp(key, "datehourago")) {
+                        newlog->flags |= LOG_FLAG_DATEHOURAGO;
+                    } 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, "su")) {
+                        int rv;
+                        mode_t tmp_mode = NO_MODE;
+                        free(key);
+                        key = isolateLine(&start, &buf, length);
+                        if (key == NULL)
+                            continue;
+
+                        rv = readModeUidGid(configFile, lineNum, key, "su",
+                                            &tmp_mode, &newlog->suUid,
+                                            &newlog->suGid);
+                        if (rv == -1) {
+                            RAISE_ERROR();
+                        }
+                        else if (tmp_mode != NO_MODE) {
+                            message(MESS_ERROR, "%s:%d extra arguments for "
+                                    "su\n", configFile, lineNum);
+                            RAISE_ERROR();
+                        }
+                        else if (newlog->suUid == NO_UID) {
+                            message(MESS_ERROR, "%s:%d no user for "
+                                    "su\n", configFile, lineNum);
+                            RAISE_ERROR();
+                        }
+                        else if (newlog->suGid == NO_GID) {
+                            message(MESS_ERROR, "%s:%d no group for "
+                                    "su\n", configFile, lineNum);
+                            RAISE_ERROR();
+                        }
+
+                        newlog->flags |= LOG_FLAG_SU;
+                    } else if (!strcmp(key, "create")) {
+                        int rv;
+
+                        free(key);
+                        key = isolateLine(&start, &buf, length);
+                        if (key == NULL)
+                            continue;
+
+                        rv = readModeUidGid(configFile, lineNum, key, "create",
+                                            &newlog->createMode, &newlog->createUid,
+                                            &newlog->createGid);
+                        if (rv == -1) {
+                            RAISE_ERROR();
+                        }
+
+                        newlog->flags |= LOG_FLAG_CREATE;
+                    } else if (!strcmp(key, "createolddir")) {
+                        int rv;
+
+                        free(key);
+                        key = isolateLine(&start, &buf, length);
+                        if (key == NULL)
+                            continue;
+
+                        rv = readModeUidGid(configFile, lineNum, key, "createolddir",
+                                            &newlog->olddirMode, &newlog->olddirUid,
+                                            &newlog->olddirGid);
+                        if (rv == -1) {
+                            RAISE_ERROR();
+                        }
+
+                        newlog->flags |= LOG_FLAG_OLDDIRCREATE;
+                    } else if (!strcmp(key, "nocreateolddir")) {
+                        newlog->flags &= ~LOG_FLAG_OLDDIRCREATE;
+                    } else if (!strcmp(key, "nocreate")) {
+                        newlog->flags &= ~LOG_FLAG_CREATE;
+                    } else if (!strcmp(key, "size") || !strcmp(key, "minsize") ||
+                            !strcmp(key, "maxsize")) {
+                        char *opt = key;
+
+                        key = isolateValue(configFile, lineNum, opt, &start, &buf, length);
+                        if (key && key[0]) {
+                            off_t size;
+                            unsigned long multiplier;
+                            const size_t l = strlen(key) - 1;
+                            if (key[l] == 'k' || 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((unsigned char)key[l])) {
+                                free(opt);
+                                message(MESS_ERROR, "%s:%d unknown unit '%c'\n",
+                                        configFile, lineNum, key[l]);
+                                RAISE_ERROR();
+                            } else {
+                                multiplier = 1;
+                            }
+
+                            size = (off_t) (multiplier * strtoull(key, &chptr, 0));
+                            if (*chptr || size < 0) {
+                                message(MESS_ERROR, "%s:%d bad size '%s'\n",
+                                        configFile, lineNum, key);
+                                free(opt);
+                                RAISE_ERROR();
+                            }
+                            if (!strncmp(opt, "size", 4)) {
+                                set_criterium(&newlog->criterium, ROT_SIZE, &criterium_set);
+                                newlog->threshold = size;
+                            } else if (!strncmp(opt, "maxsize", 7)) {
+                                newlog->maxsize = size;
+                            } else {
+                                newlog->minsize = size;
+                            }
+                            free(opt);
+                        }
+                        else {
+                            free(opt);
+                            continue;
+                        }
+                    } else if (!strcmp(key, "shredcycles")) {
+                        free(key);
+                        key = isolateValue(configFile, lineNum, "shred cycles",
+                                           &start, &buf, length);
+                        if (key == NULL)
+                            continue;
+                        newlog->shred_cycles = (int)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 if (!strcmp(key, "hourly")) {
+                        set_criterium(&newlog->criterium, ROT_HOURLY, &criterium_set);
+                    } else if (!strcmp(key, "daily")) {
+                        set_criterium(&newlog->criterium, ROT_DAYS, &criterium_set);
+                        newlog->threshold = 1;
+                    } else if (!strcmp(key, "monthly")) {
+                        set_criterium(&newlog->criterium, ROT_MONTHLY, &criterium_set);
+                    } else if (!strcmp(key, "weekly")) {
+                        unsigned weekday;
+                        char tmp;
+                        set_criterium(&newlog->criterium, ROT_WEEKLY, &criterium_set);
+                        free(key);
+                        key = isolateLine(&start, &buf, length);
+                        if (key == NULL || key[0] == '\0') {
+                            /* default to Sunday if no argument was given */
+                            newlog->weekday = 0;
+                            continue;
+                        }
+
+                        if (1 == sscanf(key, "%u%c", &weekday, &tmp) && weekday <= 7) {
+                            /* use the selected weekday, 7 means "once per week" */
+                            newlog->weekday = weekday;
+                            continue;
+                        }
+                        message(MESS_ERROR, "%s:%d bad weekly directive '%s'\n",
+                                configFile, lineNum, key);
+                        goto error;
+                    } else if (!strcmp(key, "yearly")) {
+                        set_criterium(&newlog->criterium, ROT_YEARLY, &criterium_set);
+                    } else if (!strcmp(key, "rotate")) {
+                        free(key);
+                        key = isolateValue(configFile, lineNum, "rotate count", &start,
+                                           &buf, length);
+                        if (key == NULL)
+                            continue;
+                        newlog->rotateCount = (int)strtol(key, &chptr, 0);
+                        if (*chptr || newlog->rotateCount < -1) {
+                            message(MESS_ERROR,
+                                    "%s:%d bad rotation count '%s'\n",
+                                    configFile, lineNum, key);
+                            RAISE_ERROR();
+                        }
+                    } else if (!strcmp(key, "start")) {
+                        free(key);
+                        key = isolateValue(configFile, lineNum, "start count", &start,
+                                           &buf, length);
+                        if (key == NULL)
+                            continue;
+                        newlog->logStart = (int)strtoul(key, &chptr, 0);
+                        if (*chptr || newlog->logStart < 0) {
+                            message(MESS_ERROR, "%s:%d bad start count '%s'\n",
+                                    configFile, lineNum, key);
+                            RAISE_ERROR();
+                        }
+                    } else if (!strcmp(key, "minage")) {
+                        free(key);
+                        key = isolateValue(configFile, lineNum, "minage count", &start,
+                                           &buf, length);
+                        if (key == NULL)
+                            continue;
+                        newlog->rotateMinAge = (int)strtoul(key, &chptr, 0);
+                        if (*chptr || newlog->rotateMinAge < 0) {
+                            message(MESS_ERROR, "%s:%d bad minimum age '%s'\n",
+                                    configFile, lineNum, start);
+                            RAISE_ERROR();
+                        }
+                    } else if (!strcmp(key, "maxage")) {
+                        free(key);
+                        key = isolateValue(configFile, lineNum, "maxage count", &start,
+                                           &buf, length);
+                        if (key == NULL)
+                            continue;
+                        newlog->rotateAge = (int)strtoul(key, &chptr, 0);
+                        if (*chptr || newlog->rotateAge < 0) {
+                            message(MESS_ERROR, "%s:%d bad maximum age '%s'\n",
+                                    configFile, lineNum, start);
+                            RAISE_ERROR();
+                        }
+                    } 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))) {
+                            RAISE_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, "preremove")) {
+                        freeLogItem (preremove);
+                        scriptStart = start;
+                        scriptDest = &newlog->preremove;
+                        state = STATE_LOAD_SCRIPT;
+                    } else if (!strcmp(key, "tabooext")) {
+                        char *endtag;
+
+                        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);
+                        key = isolateValue(configFile, lineNum, "tabooext", &start,
+                                           &buf, length);
+                        if (key == NULL)
+                            continue;
+                        endtag = key;
+                        if (*endtag == '+') {
+                            endtag++;
+                            while (isspace((unsigned char)*endtag) && *endtag)
+                                endtag++;
+                        } else {
+                            free_2d_array(tabooPatterns, tabooCount);
+                            tabooCount = 0;
+                            /* realloc of NULL is safe by definition */
+                            tabooPatterns = NULL;
+                        }
+
+                        while (*endtag) {
+                            int bytes;
+                            char *pattern = NULL;
+
+                            chptr = endtag;
+                            while (!isspace((unsigned char)*chptr) && *chptr != ',' && *chptr)
+                                chptr++;
+
+                            /* accept only non-empty patterns to avoid exclusion of everything */
+                            if (endtag < chptr) {
+                                char **tmp = realloc(tabooPatterns, sizeof(*tabooPatterns) *
+                                        (tabooCount + 1));
+                                if (tmp == NULL) {
+                                    message_OOM();
+                                    RAISE_ERROR();
+                                }
+                                tabooPatterns = tmp;
+                                bytes = asprintf(&pattern, "*%.*s", (int)(chptr - endtag), endtag);
+
+                                /* should test for malloc() failure */
+                                assert(bytes != -1);
+                                tabooPatterns[tabooCount] = pattern;
+                                tabooCount++;
+                            }
+
+                            endtag = chptr;
+                            if (*endtag == ',')
+                                endtag++;
+                            while (*endtag && isspace((unsigned char)*endtag))
+                                endtag++;
+                        }
+                    } else if (!strcmp(key, "taboopat")) {
+                        char *endtag;
+
+                        if (newlog != defConfig) {
+                            message(MESS_ERROR,
+                                    "%s:%d taboopat may not appear inside "
+                                    "of log file definition\n", configFile,
+                                    lineNum);
+                            state = STATE_ERROR;
+                            continue;
+                        }
+                        free(key);
+                        key = isolateValue(configFile, lineNum, "taboopat", &start,
+                                           &buf, length);
+                        if (key == NULL)
+                            continue;
+
+                        endtag = key;
+                        if (*endtag == '+') {
+                            endtag++;
+                            while (isspace((unsigned char)*endtag) && *endtag)
+                                endtag++;
+                        } else {
+                            free_2d_array(tabooPatterns, tabooCount);
+                            tabooCount = 0;
+                            /* realloc of NULL is safe by definition */
+                            tabooPatterns = NULL;
+                        }
+
+                        while (*endtag) {
+                            int bytes;
+                            char *pattern = NULL;
+                            char **tmp;
+
+                            chptr = endtag;
+                            while (!isspace((unsigned char)*chptr) && *chptr != ',' && *chptr)
+                                chptr++;
+
+                            tmp = realloc(tabooPatterns, sizeof(*tabooPatterns) *
+                                    (tabooCount + 1));
+                            if (tmp == NULL) {
+                                message_OOM();
+                                RAISE_ERROR();
+                            }
+                            tabooPatterns = tmp;
+                            bytes = asprintf(&pattern, "%.*s", (int)(chptr - endtag), endtag);
+
+                            /* should test for malloc() failure */
+                            assert(bytes != -1);
+                            tabooPatterns[tabooCount] = pattern;
+                            tabooCount++;
+
+                            endtag = chptr;
+                            if (*endtag == ',')
+                                endtag++;
+                            while (*endtag && isspace((unsigned char)*endtag))
+                                endtag++;
+                        }
+                    } else if (!strcmp(key, "include")) {
+                        int rv;
+
+                        free(key);
+                        key = isolateValue(configFile, lineNum, "include", &start,
+                                           &buf, length);
+                        if (key == NULL)
+                            continue;
+
+                        if (key[0] == '~' && key[1] == '/') {
+                            /* replace '~' with content of $HOME cause low-level functions
+                             * like stat() do not support the glob ~
+                             */
+                            const char *env_home = secure_getenv("HOME");
+                            char *new_key = NULL;
+
+                            if (!env_home) {
+                                const struct passwd *pwd = getpwuid(getuid());
+                                message(MESS_DEBUG,
+                                        "%s:%d cannot get HOME directory from environment "
+                                        "to replace ~/ in include directive\n",
+                                        configFile, lineNum);
+                                if (!pwd) {
+                                    message(MESS_ERROR, "%s:%d cannot get passwd entry for "
+                                            "running user %u: %s\n",
+                                           configFile, lineNum, getuid(), strerror(errno));
+                                    RAISE_ERROR();
+                                }
+                                env_home = pwd->pw_dir;
+                            }
+
+                            if (asprintf(&new_key, "%s/%s", env_home, key + 2) == -1) {
+                                message_OOM();
+                                RAISE_ERROR();
+                            }
+                            message(MESS_DEBUG, "%s:%d replaced %s with '%s' for include directive\n",
+                                    configFile, lineNum, key, env_home);
+                            free(key);
+                            key = new_key;
+                        }
+
+                        message(MESS_DEBUG, "including %s\n", key);
+                        if (recursion_depth >= MAX_NESTING) {
+                            message(MESS_ERROR, "%s:%d include nesting too deep\n",
+                                    configFile, lineNum);
+                            logerror = 1;
+                            continue;
+                        }
+
+                        ++recursion_depth;
+                        rv = readConfigPath(key, newlog);
+                        --recursion_depth;
+
+                        if (rv) {
+                            logerror = 1;
+                            continue;
+                        }
+                    } else if (!strcmp(key, "olddir")) {
+                        freeLogItem (oldDir);
+
+                        if (!(newlog->oldDir = readPath(configFile, lineNum,
+                                        "olddir", &start, &buf, length))) {
+                            RAISE_ERROR();
+                        }
+                        message(MESS_DEBUG, "olddir is now %s\n", newlog->oldDir);
+                    } else if (!strcmp(key, "extension")) {
+                        free(key);
+                        key = isolateValue(configFile, lineNum, "extension name", &start,
+                                           &buf, length);
+                        if (key == NULL)
+                            continue;
+                        freeLogItem (extension);
+                        newlog->extension = key;
+                        key = NULL;
+                        message(MESS_DEBUG, "extension is now %s\n", newlog->extension);
+
+                    } else if (!strcmp(key, "addextension")) {
+                        free(key);
+                        key = isolateValue(configFile, lineNum, "addextension name", &start,
+                                           &buf, length);
+                        if (key == NULL)
+                            continue;
+                        freeLogItem (addextension);
+                        newlog->addextension = key;
+                        key = NULL;
+                        message(MESS_DEBUG, "addextension is now %s\n",
+                                newlog->addextension);
+
+                    } else if (!strcmp(key, "compresscmd")) {
+                        char *compresscmd_full;
+                        const char *compresscmd_base;
+                        unsigned i;
+
+                        freeLogItem (compress_prog);
+
+                        if (!
+                                (newlog->compress_prog =
+                                 readPath(configFile, lineNum, "compress", &start, &buf, length))) {
+                            RAISE_ERROR();
+                        }
+
+                        message(MESS_DEBUG, "compress_prog is now %s\n",
+                                newlog->compress_prog);
+
+                        compresscmd_full = strdup(newlog->compress_prog);
+                        if (compresscmd_full == NULL) {
+                            message_OOM();
+                            RAISE_ERROR();
+                        }
+
+                        compresscmd_base = basename(compresscmd_full);
+
+                        /* we check whether we changed the compress_cmd. In case we use the appropriate extension
+                           as listed in compress_cmd_list */
+                        for(i = 0; i < compress_cmd_list_size; i++) {
+                            if (!strcmp(compress_cmd_list[i].cmd, compresscmd_base)) {
+                                freeLogItem (compress_ext);
+                                newlog->compress_ext = strdup(compress_cmd_list[i].ext);
+                                if (newlog->compress_ext == NULL) {
+                                    message_OOM();
+                                    free(compresscmd_full);
+                                    RAISE_ERROR();
+                                }
+                                message(MESS_DEBUG, "compress_ext was changed to %s\n", newlog->compress_ext);
+                                break;
+                            }
+                        }
+                        free(compresscmd_full);
+                    } else if (!strcmp(key, "uncompresscmd")) {
+                        freeLogItem (uncompress_prog);
+
+                        if (!
+                                (newlog->uncompress_prog =
+                                 readPath(configFile, lineNum, "uncompress",
+                                          &start, &buf, length))) {
+                            RAISE_ERROR();
+                        }
+
+                        message(MESS_DEBUG, "uncompress_prog is now %s\n",
+                                newlog->uncompress_prog);
+
+                    } else if (!strcmp(key, "compressoptions")) {
+                        char *options;
+
+                        if (newlog->compress_options_list) {
+                            free(newlog->compress_options_list);
+                            newlog->compress_options_list = NULL;
+                            newlog->compress_options_count = 0;
+                        }
+
+                        if (!(options = isolateLine(&start, &buf, length))) {
+                            RAISE_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);
+                            RAISE_ERROR();
+                        }
+
+                        message(MESS_DEBUG, "compress_options is now %s\n",
+                                options);
+                        free(options);
+                    } else if (!strcmp(key, "compressext")) {
+                        freeLogItem (compress_ext);
+
+                        if (!
+                                (newlog->compress_ext =
+                                 readPath(configFile, lineNum, "compress-ext",
+                                          &start, &buf, length))) {
+                            RAISE_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, key);
+                        if (*start != '\n')
+                            state = STATE_SKIP_LINE;
+                    }
+                } else if (*start == '/' || *start == '"' || *start == '\''
+#ifdef GLOB_TILDE
+                        || *start == '~'
+#endif
+                        ) {
+                    char *glob_string;
+                    size_t glob_count;
+                    int argc, argNum;
+                    const char **argv;
+                    in_config = 0;
+                    if (newlog != defConfig) {
+                        message(MESS_ERROR, "%s:%d unexpected log filename\n",
+                                configFile, lineNum);
+                        state = STATE_ERROR;
+                        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);
+
+                    if (!newlog->compress_prog || !newlog->uncompress_prog || !newlog->compress_ext) {
+                        message_OOM();
+                        goto error;
+                    }
+
+                    /* 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;
+
+                    glob_string = parseGlobString(configFile, lineNum, buf, length, &start);
+                    if (glob_string)
+                        in_config = 1;
+                    else
+                        /* error already printed */
+                        goto error;
+
+                    if (poptParseArgvString(glob_string, &argc, &argv)) {
+                        message(MESS_ERROR, "%s:%d error parsing filename\n",
+                                configFile, lineNum);
+                        free(glob_string);
+                        goto error;
+                    } else if (argc < 1) {
+                        message(MESS_ERROR,
+                                "%s:%d { expected after log file name(s)\n",
+                                configFile, lineNum);
+                        free(glob_string);
+                        goto error;
+                    }
+
+                    newlog->files = NULL;
+                    newlog->numFiles = 0;
+                    for (argNum = 0; argNum < argc; argNum++) {
+                        char **tmp;
+                        int rc;
+                        glob_t globResult;
+
+                        if (globerr_msg) {
+                            free(globerr_msg);
+                            globerr_msg = NULL;
+                        }
+
+                        rc = glob(argv[argNum], GLOB_NOCHECK
+#ifdef GLOB_TILDE
+                                | GLOB_TILDE
+#endif
+                                , 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;
+                        }
+
+                        tmp = realloc(newlog->files,
+                                    sizeof(*newlog->files) * (newlog->numFiles +
+                                        globResult.
+                                        gl_pathc));
+                        if (tmp == NULL) {
+                            message_OOM();
+                            logerror = 1;
+                            goto duperror;
+                        }
+
+                        newlog->files = tmp;
+
+                        for (glob_count = 0; glob_count < globResult.gl_pathc; glob_count++) {
+                            struct logInfo *log;
+
+                            /* if we glob directories we can get false matches */
+                            if (!lstat(globResult.gl_pathv[glob_count], &sb) &&
+                                    S_ISDIR(sb.st_mode)) {
+                                continue;
+                            }
+
+                            for (log = logs.tqh_first; log != NULL;
+                                    log = log->list.tqe_next) {
+                                unsigned k;
+                                for (k = 0; k < log->numFiles; k++) {
+                                    if (!strcmp(log->files[k],
+                                                globResult.gl_pathv[glob_count])) {
+                                        message(MESS_ERROR,
+                                                "%s:%d duplicate log entry for %s\n",
+                                                configFile, lineNum,
+                                                globResult.gl_pathv[glob_count]);
+                                        logerror = 1;
+                                        goto duperror;
+                                    }
+                                }
+                            }
+
+                            newlog->files[newlog->numFiles] =
+                                strdup(globResult.gl_pathv[glob_count]);
+                            if (newlog->files[newlog->numFiles] == NULL) {
+                                message_OOM();
+                                logerror = 1;
+                                goto duperror;
+                            }
+                            newlog->numFiles++;
+                        }
+duperror:
+                        globfree(&globResult);
+                    }
+
+                    newlog->pattern = glob_string;
+
+                    free(argv);
+
+                } else if (*start == '}') {
+                    if (newlog == defConfig) {
+                        message(MESS_ERROR, "%s:%d unexpected }\n", configFile,
+                                lineNum);
+                        goto error;
+                    }
+                    if (!in_config) {
+                        message(MESS_ERROR, "%s:%d unexpected } (missing previous '{')\n", configFile,
+                                lineNum);
+                        goto error;
+                    }
+                    in_config = 0;
+                    if (globerr_msg) {
+                        if (!(newlog->flags & LOG_FLAG_MISSINGOK))
+                            message(MESS_ERROR, "%s", globerr_msg);
+                        free(globerr_msg);
+                        globerr_msg = NULL;
+                        if (!(newlog->flags & LOG_FLAG_MISSINGOK))
+                            goto error;
+                    }
+
+                    if (newlog->oldDir) {
+                        unsigned j;
+                        for (j = 0; j < newlog->numFiles; j++) {
+                            char *ld;
+                            char *dirpath;
+                            const char *dirName;
+                            struct stat sb2;
+
+                            dirpath = strdup(newlog->files[j]);
+                            if (dirpath == NULL) {
+                                message_OOM();
+                                goto error;
+                            }
+
+                            dirName = dirname(dirpath);
+                            if (stat(dirName, &sb2)) {
+                                if (!(newlog->flags & LOG_FLAG_MISSINGOK)) {
+                                    message(MESS_ERROR,
+                                            "%s:%d error verifying log file "
+                                            "path %s: %s\n", configFile, lineNum,
+                                            dirName, strerror(errno));
+                                    free(dirpath);
+                                    goto error;
+                                }
+                                else {
+                                    message(MESS_DEBUG,
+                                            "%s:%d verifying log file "
+                                            "path failed %s: %s, log is probably missing, "
+                                            "but missingok is set, so this is not an error.\n",
+                                            configFile, lineNum,
+                                            dirName, strerror(errno));
+                                    free(dirpath);
+                                    continue;
+                                }
+                            }
+                            ld = malloc(strlen(dirName) + strlen(newlog->oldDir) + 2);
+                            if (ld == NULL) {
+                                message_OOM();
+                                free(dirpath);
+                                goto error;
+                            }
+                            sprintf(ld, "%s/%s", dirName, newlog->oldDir);
+                            free(dirpath);
+
+                            if (newlog->oldDir[0] != '/') {
+                                dirName = ld;
+                            }
+                            else {
+                                dirName = newlog->oldDir;
+                            }
+
+                            if (stat(dirName, &sb)) {
+                                if (errno == ENOENT && (newlog->flags & LOG_FLAG_OLDDIRCREATE)) {
+                                    int ret;
+                                    if (newlog->flags & LOG_FLAG_SU) {
+                                        if (switch_user(newlog->suUid, newlog->suGid) != 0) {
+                                            free(ld);
+                                            goto error;
+                                        }
+                                    }
+                                    ret = mkpath(dirName, newlog->olddirMode,
+                                            newlog->olddirUid, newlog->olddirGid);
+                                    if (newlog->flags & LOG_FLAG_SU) {
+                                        if (switch_user_back() != 0) {
+                                            free(ld);
+                                            goto error;
+                                        }
+                                    }
+                                    if (ret) {
+                                        free(ld);
+                                        goto error;
+                                    }
+                                }
+                                else {
+                                    message(MESS_ERROR, "%s:%d error verifying olddir "
+                                            "path %s: %s\n", configFile, lineNum,
+                                            dirName, strerror(errno));
+                                    free(ld);
+                                    goto error;
+                                }
+                            }
+
+                            free(ld);
+
+                            if (sb.st_dev != sb2.st_dev
+                                    && !(newlog->flags & (LOG_FLAG_COPYTRUNCATE | LOG_FLAG_COPY | LOG_FLAG_TMPFILENAME))) {
+                                message(MESS_ERROR,
+                                        "%s:%d olddir %s and log file %s "
+                                        "are on different devices\n", configFile,
+                                        lineNum, newlog->oldDir, newlog->files[j]);
+                                goto error;
+                            }
+                        }
+                    }
+
+                    criterium_set = 0;
+                    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;
+                }
+                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((unsigned char)*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);
+                }
+                else
+                    state = (state & STATE_SKIP_CONFIG) ? STATE_SKIP_CONFIG : STATE_DEFAULT;
+                break;
+            case STATE_ERROR:
+                assert(newlog != defConfig);
+
+                message(MESS_ERROR, "found error in %s, skipping\n",
+                        newlog->pattern ? newlog->pattern : "log config");
+
+                logerror = 1;
+                state = STATE_SKIP_CONFIG;
+                break;
+            case STATE_LOAD_SCRIPT:
+            case STATE_LOAD_SCRIPT | STATE_SKIP_CONFIG:
+                free(key);
+                key = isolateWord(&start, &buf, length);
+                if (key == NULL)
+                    continue;
+
+                if (strcmp(key, "endscript") == 0) {
+                    if (state & STATE_SKIP_CONFIG) {
+                        state = STATE_SKIP_CONFIG;
+                    }
+                    else {
+                        const char *endtag = start - 9;
+                        while (*endtag != '\n')
+                            endtag--;
+                        endtag++;
+                        *scriptDest = strndup(scriptStart, (size_t)(endtag - scriptStart));
+                        if (*scriptDest == NULL) {
+                            message_OOM();
+                            goto error;
+                        }
+
+                        scriptDest = NULL;
+                        scriptStart = NULL;
+                    }
+                    state = (state & STATE_SKIP_CONFIG) ? STATE_SKIP_CONFIG : STATE_DEFAULT;
+                }
+                else {
+                    state = (*start == '\n' ? 0 : STATE_SKIP_LINE) |
+                        STATE_LOAD_SCRIPT |
+                        ((state & STATE_SKIP_CONFIG) ? STATE_SKIP_CONFIG : 0);
+                }
+                break;
+            case STATE_SKIP_CONFIG:
+                if (*start == '}') {
+                    state = STATE_DEFAULT;
+                    freeTailLogs(1);
+                    newlog = defConfig;
+                }
+                else {
+                    free(key);
+                    key = isolateWord(&start, &buf, length);
+                    if (key == NULL)
+                        continue;
+                    if (
+                            (strcmp(key, "postrotate") == 0) ||
+                            (strcmp(key, "prerotate") == 0) ||
+                            (strcmp(key, "firstaction") == 0) ||
+                            (strcmp(key, "lastaction") == 0) ||
+                            (strcmp(key, "preremove") == 0)
+                            ) {
+                        state = STATE_LOAD_SCRIPT | STATE_SKIP_CONFIG;
+                    }
+                    else {
+                        /* isolateWord moves the "start" pointer.
+                         * If we have a line like
+                         *    rotate 5
+                         * after isolateWord "start" points to "5" and it
+                         * is OK to skip the line, but if we have a line
+                         * like the following
+                         *    nocompress
+                         * after isolateWord "start" points to "\n". In
+                         * this case if we skip a line, we skip the next
+                         * line, not the current "nocompress" one,
+                         * because in the for cycle the "start"
+                         * pointer is increased by one and, after this,
+                         * "start" points to the beginning of the next line.
+                         */
+                        if (*start != '\n') {
+                            state = STATE_SKIP_LINE | STATE_SKIP_CONFIG;
+                        }
+                    }
+                }
+                break;
+            default:
+                message(MESS_FATAL,
+                        "%s: %d: readConfigFile() unknown state\n",
+                        configFile, lineNum);
+        }
+        if (*start == '\n') {
+            lineNum++;
+        }
+
+next_state: ;
+    }
+
+    if (scriptStart) {
+        message(MESS_ERROR,
+                "%s:prerotate, postrotate or preremove without endscript\n",
+                configFile);
+        goto error;
+    }
+
+    free(key);
+
+    munmap(buf, length);
+    close(fd);
+    return logerror;
+error:
+    /* free is a NULL-safe operation */
+    free(key);
+    munmap(buf, length);
+    close(fd);
+    return 1;
+}
+
+/* vim: set et sw=4 ts=4: */
Index: create-3.18.0-patch/logrotate-3.18.0-new/logrotate.8.in
===================================================================
--- create-3.18.0-patch/logrotate-3.18.0-new/logrotate.8.in	(nonexistent)
+++ create-3.18.0-patch/logrotate-3.18.0-new/logrotate.8.in	(revision 5)
@@ -0,0 +1,755 @@
+.TH LOGROTATE 8 "@VERSION@" "Linux" "System Administrator's Manual"
+.\" Per groff_man(7), the TQ macro should be copied from an-ext.tmac when
+.\" not running under groff.  That's not quite right; not all groff
+.\" installations include this macro.  So bring it in with another name
+.\" unconditionally.
+.\" Continuation line for .TP header.
+.de tq
+.  br
+.  ns
+.  TP \\$1\" no doublequotes around argument!
+..
+.\}
+.SH NAME
+
+logrotate \(hy rotates, compresses, and mails system logs
+
+.SH SYNOPSIS
+
+\fBlogrotate\fR
+\fR[\fB\-\-force\fR]
+\fR[\fB\-\-debug\fR]
+\fR[\fB\-\-state\fR \fIfile\fR]
+\fR[\fB\-\-skip-state-lock\fR]
+\fR[\fB\-\-verbose\fR]
+\fR[\fB\-\-log\fR \fIfile\fR]
+\fR[\fB\-\-mail\fR \fIcommand\fR]
+\fIconfig_file\fR
+\fR[\fIconfig_file2 ...\fR]
+
+.SH DESCRIPTION
+
+\fBlogrotate\fR is designed to ease administration of systems that generate
+large numbers of log files.  It allows automatic rotation, compression,
+removal, and mailing of log files.  Each log file may be handled daily,
+weekly, monthly, or when it grows too large.
+.P
+Normally, \fBlogrotate\fR is run as a daily cron job.  It will not modify
+a log more than once in one day unless the criterion for that log is
+based on the log's size and \fBlogrotate\fR is being run more than once
+each day, or unless the \fB\-f\fR or \fB\-\-force\fR option is used.
+.P
+Any number of config files may be given on the command line.  Later config
+files may override the options given in earlier files, so the order
+in which the \fBlogrotate\fR config files are listed is important.
+Normally, a single config file which includes any other config files
+which are needed should be used.  See below for more information on how
+to use the \fBinclude\fR directive to accomplish this.  If a directory
+is given on the command line, every file in that directory is used as
+a config file.
+.P
+If no command line arguments are given, \fBlogrotate\fR will print
+version and copyright information, along with a short usage summary.  If
+any errors occur while rotating logs, \fBlogrotate\fR will exit with
+non-zero status.
+
+.SH OPTIONS
+
+.TP
+\fB\-f\fR, \fB\-\-force\fR
+Tells \fBlogrotate\fR to force the rotation, even if it doesn't think
+this is necessary.  Sometimes this is useful after adding new entries to
+a \fBlogrotate\fR config file, or if old log files have been removed
+by hand, as the new files will be created, and logging will continue
+correctly.
+
+.TP
+\fB\-d\fR, \fB\-\-debug\fR
+Turn on debug mode, which means that no changes are made to the logs and the
+\fBlogrotate\fR state file is not updated.  Only debug messages are printed.
+
+.TP
+\fB\-s\fR, \fB\-\-state\fR \fIstatefile\fR
+Tells \fBlogrotate\fR to use an alternate state file.  This is useful
+if \fBlogrotate\fR is being run as a different user for various sets of
+log files.  To prevent parallel execution \fBlogrotate\fR by default
+acquires a lock on the state file, if it cannot be acquired \fBlogrotate\fR
+will exit with value 3.  The default state file is \fI@STATE_FILE_PATH@\fR.
+
+.TP
+\fB\-\-skip-state-lock\fR
+Do not lock the state file, for example if locking is unsupported or prohibited.
+
+.TP
+\fB\-v\fR, \fB\-\-verbose\fR
+Turns on verbose mode, for example to display messages during rotation.
+
+.TP
+\fB\-l\fR, \fB\-\-log\fR \fIfile\fR
+Tells \fBlogrotate\fR to log verbose output into the log_file.  The verbose
+output logged to that file is the same as when running \fBlogrotate\fR with
+\fB-v\fR switch.  The log file is overwritten on every \fBlogrotate\fR
+execution.
+
+.TP
+\fB\-m\fR, \fB\-\-mail\fR \fIcommand\fR
+Tells \fBlogrotate\fR which command to use when mailing logs.  This
+command should accept the following arguments:
+.IP
+1) the subject of the message given with '-s subject'
+.br
+2) the recipient.
+.IP
+The command must then read a message on standard input
+and mail it to the recipient.  The default mail command is
+\fI@DEFAULT_MAIL_COMMAND@\fR.
+
+.TP
+\fB\-\-usage\fR
+Prints a short usage message.
+
+.TP
+\fB\-?\fR, \fB\-\-help\fR
+Prints help message.
+
+.TP
+\fB\-\-version\fR
+Display version information.
+
+
+.SH CONFIGURATION FILE
+
+\fBlogrotate\fR reads everything about the log files it should be handling
+from the series of configuration files specified on the command line.  Each
+configuration file can set global options (local definitions override
+global ones, and later definitions override earlier ones) and specify
+logfiles to rotate.  Global options do not affect preceding include
+directives.  A simple configuration file looks like this:
+
+.nf
+.ta +8n
+# sample logrotate configuration file
+compress
+
+/var/log/messages {
+    rotate 5
+    weekly
+    postrotate
+        /usr/bin/killall \-HUP syslogd
+    endscript
+}
+
+"/var/log/httpd/access.log" /var/log/httpd/error.log {
+    rotate 5
+    mail recipient@example.org
+    size 100k
+    sharedscripts
+    postrotate
+        /usr/bin/killall \-HUP httpd
+    endscript
+}
+
+/var/log/news/* {
+    monthly
+    rotate 2
+    olddir /var/log/news/old
+    missingok
+    postrotate
+        kill \-HUP $(cat /var/run/inn.pid)
+    endscript
+    nocompress
+}
+
+~/log/*.log {}
+
+.fi
+
+.PP
+The first few lines set global options; in the example, logs are
+compressed after they are rotated.  Note that comments may appear
+anywhere in the config file as long as the first non-whitespace
+character on the line is a \fB#\fR.
+
+Values are separated from directives by whitespace and/or an optional =.
+Numbers must be specified in a format understood by \fBstrtoul\fR(3).
+
+The next section of the config file defines how to handle the log file
+\fI/var/log/messages\fR.  The log will go through five weekly rotations before
+being removed.  After the log file has been rotated (but before the old
+version of the log has been compressed), the command
+\fI/usr/bin/killall \-HUP syslogd\fR will be executed.
+
+The next section defines the parameters for both
+\fI/var/log/httpd/access.log\fR and \fI/var/log/httpd/error.log\fR.
+Each is rotated whenever it grows over 100\ kilobytes in size, and the old logs
+files are mailed (uncompressed) to recipient@\:example.org after going through 5
+rotations, rather than being removed.  The \fBsharedscripts\fR means that
+the \fBpostrotate\fR script will only be run once (after the old logs have
+been compressed), not once for each log which is rotated.
+Note that log file names may be enclosed in
+quotes (and that quotes are required if the name contains spaces).
+Normal shell quoting rules apply, with \fB'\fR, \fB"\fR, and \fB\e\fR
+characters supported.
+
+The next section defines the parameters for all of the files in
+\fI/var/log/news\fR. Each file is rotated on a monthly basis.  This is
+considered a single rotation directive and if errors occur for more than
+one file, the log files are not compressed.
+
+The last section uses tilde expansion to rotate log files in the home
+directory of the current user.  This is only available, if your glob
+library supports tilde expansion.  GNU glob does support this.
+
+Please use wildcards with caution.  If you specify *, \fBlogrotate\fR will
+rotate all files, including previously rotated ones.  A way around this
+is to use the \fBolddir\fR directive or a more exact wildcard (such as *.log).
+
+Here is more information on the directives which may be included in
+a \fBlogrotate\fR configuration file:
+
+.SH CONFIGURATION FILE DIRECTIVES
+These directives may be included in a \fBlogrotate\fR configuration file:
+
+.SS Rotation
+
+.TP
+\fBrotate \fIcount\fR
+Log files are rotated \fIcount\fR times before being removed or mailed to the
+address specified in a \fBmail\fR directive.  If \fIcount\fR is 0, old versions
+are removed rather than rotated.  If \fIcount\fR is \-1, old logs are not
+removed at all, except they are affected by \fBmaxage\fR (use with caution, may
+waste performance and disk space).  Default is 0.
+
+.TP
+\fBolddir \fIdirectory\fR
+Logs are moved into \fIdirectory\fR for rotation.  The \fIdirectory\fR must be
+on the same physical device as the log file being rotated, unless \fBcopy\fR,
+\fBcopytruncate\fR or \fBrenamecopy\fR option is used.  The \fIdirectory\fR
+is assumed to be relative to the directory holding the log file
+unless an absolute path name is specified.  When this option is used all
+old versions of the log end up in \fIdirectory\fR.  This option may be
+overridden by the \fBnoolddir\fR option.
+
+.TP
+\fBnoolddir\fR
+Logs are rotated in the directory they normally reside in (this
+overrides the \fBolddir\fR option).
+
+.TP
+\fBsu \fIuser\fR \fIgroup\fR
+Rotate log files set under this user and group instead of using default
+user/group (usually root).  \fIuser\fR specifies the user used for
+rotation and \fIgroup\fR specifies the group used for rotation (see the
+section \fBUSER AND GROUP\fR for details).  If the
+user/group you specify here does not have sufficient privilege to make
+files with the ownership you've specified in a \fBcreate\fR directive,
+it will cause an error.  If \fBlogrotate\fR runs with root privileges, it is
+recommended to use the \fBsu\fR directive to rotate files in directories
+that are directly or indirectly in control of non-privileged users.
+
+.SS Frequency
+
+.TP
+\fBhourly\fR
+Log files are rotated every hour.  Note that usually \fBlogrotate\fR is
+configured to be run by cron daily.  You have to change this configuration
+and run \fBlogrotate\fR hourly to be able to really rotate logs hourly.
+
+.TP
+\fBdaily\fR
+Log files are rotated every day.
+
+.TP
+\fBweekly\fR [\fIweekday\fR]
+Log files are rotated once each \fIweekday\fR, or if the date is advanced by at
+least 7 days since the last rotation (while ignoring the exact time).  The
+\fIweekday\fR interpretation is following: 0 means Sunday, 1 means Monday,
+\&.\|.\|.\|\&, 6 means Saturday; the special value 7 means each 7 days,
+irrespectively of weekday.
+Defaults to 0 if the \fIweekday\fR argument is omitted.
+
+.TP
+\fBmonthly\fR
+Log files are rotated the first time \fBlogrotate\fR is run in a month
+(this is normally on the first day of the month).
+
+.TP
+\fByearly\fR
+Log files are rotated if the current year is not the same as the last rotation.
+
+.TP
+\fBsize \fIsize\fR
+Log files are rotated only if they grow bigger than \fIsize\fR bytes.  If
+\fIsize\fR is followed by \fIk\fR, the size is assumed to be in kilobytes.
+If the \fIM\fR is used, the size is in megabytes, and if \fIG\fR is used, the
+size is in gigabytes. So \fIsize 100\fR, \fIsize 100k\fR, \fIsize 100M\fR and
+\fIsize 100G\fR are all valid.  This option is mutually exclusive with the time
+interval options, and it causes log files to be rotated without regard for the
+last rotation time, if specified after the time criteria (the last specified
+option takes the precedence).
+
+.SS File selection
+
+.TP
+\fBmissingok\fR
+If the log file is missing, go on to the next one without issuing an error
+message.  See also \fBnomissingok\fR.
+
+.TP
+\fBnomissingok\fR
+If a log file does not exist, issue an error.  This is the default.
+
+.TP
+\fBifempty\fR
+Rotate the log file even if it is empty, overriding the \fBnotifempty\fR
+option (\fBifempty\fR is the default).
+
+.TP
+\fBnotifempty\fR
+Do not rotate the log if it is empty (this overrides the \fBifempty\fR option).
+
+.TP
+\fBminage\fR \fIcount\fR
+Do not rotate logs which are less than <count> days old.
+
+.TP
+\fBmaxage\fR \fIcount\fR
+Remove rotated logs older than <count> days.  The age is only checked
+if the logfile is to be rotated.  \fBrotate \-1\fR does not hinder removal.
+The files are mailed to the configured address if \fBmaillast\fR and
+\fBmail\fR are configured.
+
+.TP
+\fBminsize\fR \fIsize\fR
+Log files are rotated when they grow bigger than \fIsize\fR bytes, but not
+before the additionally specified time interval (\fBdaily\fR, \fBweekly\fR,
+\fBmonthly\fR, or \fByearly\fR).  The related \fBsize\fR option is similar
+except that it is mutually exclusive with the time interval options, and it
+causes log files to be rotated without regard for the last rotation time,
+if specified after the time criteria (the last specified option takes the
+precedence).  When \fBminsize\fR is used, both the size and timestamp of a
+log file are considered.
+
+.TP
+\fBmaxsize\fR \fIsize\fR
+Log files are rotated when they grow bigger than \fIsize\fR bytes even
+before the additionally specified time interval (\fBdaily\fR, \fBweekly\fR,
+\fBmonthly\fR, or \fByearly\fR).  The related \fBsize\fR option is similar
+except that it is mutually exclusive with the time interval options, and it
+causes log files to be rotated without regard for the last rotation time,
+if specified after the time criteria (the last specified option takes the
+precedence).  When \fBmaxsize\fR is used, both the size and timestamp of a
+log file are considered.
+
+.TP
+\fBtabooext\fR [+] \fIlist\fR
+The current taboo extension list is changed (see the \fBinclude\fR directive
+for information on the taboo extensions).  If a + precedes the list of
+extensions, the current taboo extension list is augmented, otherwise it
+is replaced.  At startup, the taboo extension list
+.IR ,v ,
+.IR .cfsaved ,
+.IR .disabled ,
+.IR .dpkg\-bak ,
+.IR .dpkg\-del ,
+.IR .dpkg\-dist ,
+.IR .dpkg\-new ,
+.IR .dpkg\-old ,
+.IR .rhn\-cfg\-tmp\-* ,
+.IR .rpmnew ,
+.IR .rpmorig ,
+.IR .rpmsave ,
+.IR .swp ,
+.IR .ucf\-dist ,
+.IR .ucf\-new ,
+.IR .ucf\-old ,
+.IR .new ,
+.IR .old ,
+.IR .orig ,
+.IR .bak ,
+.I ~
+
+.TP
+\fBtaboopat\fR [+] \fIlist\fR
+The current taboo glob pattern list is changed (see the \fBinclude\fR directive
+for information on the taboo extensions and patterns).  If a + precedes the list
+of patterns, the current taboo pattern list is augmented, otherwise it
+is replaced.  At startup, the taboo pattern list is empty.
+
+.SS Files and Folders
+
+.TP
+\fBcreate \fImode\fR \fIowner\fR \fIgroup\fR, \fBcreate \fIowner\fR \fIgroup\fR
+Immediately after rotation (before the \fBpostrotate\fR script is run)
+the log file is created (with the same name as the log file just rotated).
+\fImode\fR specifies the mode for the log file in octal (the same
+as \fBchmod\fR(2)), \fIowner\fR specifies the user who will own the
+log file, and \fIgroup\fR specifies the group the log file will belong
+to (see the section \fBUSER AND GROUP\fR for details).
+Any of the log file attributes may be omitted, in which case those
+attributes for the new file will use the same values as the original log
+file for the omitted attributes.  This option can be disabled using the
+\fBnocreate\fR option.
+
+.TP
+\fBnocreate\fR
+New log files are not created (this overrides the \fBcreate\fR option).
+
+.TP
+\fBcreateolddir \fImode\fR \fIowner\fR \fIgroup\fR
+If the directory specified by \fBolddir\fR directive does not exist, it is
+created. \fImode\fR specifies the mode for the \fBolddir\fR directory
+in octal (the same as \fBchmod\fR(2)), \fIowner\fR specifies the user
+who will own the \fBolddir\fR directory, and \fIgroup\fR specifies the group
+the \fBolddir\fR directory will belong to (see the section \fBUSER AND GROUP
+\fR for details).  This option can be disabled using
+the \fBnocreateolddir\fR option.
+
+.TP
+\fBnocreateolddir\fR
+\fBolddir\fR directory is not created by \fBlogrotate\fR when it does not exist.
+
+.TP
+\fBcopy\fR
+Make a copy of the log file, but don't change the original at all.
+This option can be used, for instance, to make a snapshot of the current
+log file, or when some other utility needs to truncate or parse the file.
+When this option is used, the \fBcreate\fR option will have no effect,
+as the old log file stays in place.
+
+.TP
+\fBnocopy\fR
+Do not copy the original log file and leave it in place.
+(this overrides the \fBcopy\fR option).
+
+.TP
+\fBcopytruncate\fR
+Truncate the original log file to zero size in place after creating a copy,
+instead of moving the old log file and optionally creating a new one.
+It can be used when some program cannot be told to close its logfile
+and thus might continue writing (appending) to the previous log file forever.
+Note that there is a very small time slice between copying the file and
+truncating it, so some logging data might be lost.
+When this option is used, the \fBcreate\fR option will have no effect,
+as the old log file stays in place.
+
+.TP
+\fBnocopytruncate\fR
+Do not truncate the original log file in place after creating a copy
+(this overrides the \fBcopytruncate\fR option).
+
+.TP
+\fBrenamecopy\fR
+Log file is renamed to temporary filename in the same directory by adding
+".tmp" extension to it.  After that, \fBpostrotate\fR script is run
+and log file is copied from temporary filename to final filename.  This allows
+storing rotated log files on the different devices using \fBolddir\fR
+directive. In the end, temporary filename is removed.
+
+.TP
+\fBshred\fR
+Delete log files using \fBshred\fR \-u instead of unlink().  This should
+ensure that logs are not readable after their scheduled deletion; this is
+off by default.  See also \fBnoshred\fR.
+
+.TP
+\fBnoshred\fR
+Do not use \fBshred\fR when deleting old log files.  See also \fBshred\fR.
+
+.TP
+\fBshredcycles\fR \fIcount\fR
+Asks GNU \fBshred\fR(1) to overwrite log files \fBcount\fR times before
+deletion.  Without this option, \fBshred\fR's default will be used.
+
+.SS Compression
+
+.TP
+\fBcompress\fR
+Old versions of log files are compressed with \fBgzip\fR(1) by default.
+See also \fBnocompress\fR.
+
+.TP
+\fBnocompress\fR
+Old versions of log files are not compressed.  See also \fBcompress\fR.
+
+.TP
+\fBcompresscmd\fR
+Specifies which command to use to compress log files.  The default is
+\fBgzip\fR(1).  See also \fBcompress\fR.
+
+.TP
+\fBuncompresscmd\fR
+Specifies which command to use to uncompress log files.  The default is
+\fBgunzip\fR(1).
+
+.TP
+\fBcompressext\fR
+Specifies which extension to use on compressed logfiles, if compression
+is enabled.  The default follows that of the configured compression
+command.
+
+.TP
+\fBcompressoptions\fR
+Command line options may be passed to the compression program, if one is
+in use.  The default, for \fBgzip\fR(1), is "\-6" (biased towards high
+compression at the expense of speed).
+If you use a different compression command, you may need to change the
+\fBcompressoptions\fR to match.
+
+.TP
+\fBdelaycompress\fR
+Postpone compression of the previous log file to the next rotation cycle.
+This only has effect when used in combination with \fBcompress\fR.
+It can be used when some program cannot be told to close its logfile
+and thus might continue writing to the previous log file for some time.
+
+.TP
+\fBnodelaycompress\fR
+Do not postpone compression of the previous log file to the next rotation cycle
+(this overrides the \fBdelaycompress\fR option).
+
+.SS Filenames
+
+.TP
+\fBextension \fIext\fR
+Log files with \fIext\fR extension can keep it after the rotation.
+If compression is used, the compression extension (normally \fI.gz\fR)
+appears after \fIext\fR.  For example you have a logfile named mylog.foo
+and want to rotate it to mylog.1.foo.gz instead of mylog.foo.1.gz.
+
+.TP
+\fBaddextension \fIext\fR
+Log files are given the final extension \fIext\fR after rotation.  If
+the original file already ends with \fIext\fR, the extension is not
+duplicated, but merely moved to the end, that is both \fBfilename\fR and
+\fBfilename\fIext\fR would get rotated to filename.1\fIext\fR.  If
+compression is used, the compression extension (normally \fB.gz\fR)
+appears after \fIext\fR.
+
+.TP
+\fBstart \fIcount\fR
+This is the number to use as the base for rotation.  For example, if
+you specify 0, the logs will be created with a .0 extension as they are
+rotated from the original log files.  If you specify 9, log files will
+be created with a .9, skipping 0\(en8.  Files will still be rotated the
+number of times specified with the \fBrotate\fR directive.
+
+.TP
+\fBdateext\fR
+Archive old versions of log files adding a date extension like YYYYMMDD
+instead of simply adding a number.  The extension may be configured using
+the \fBdateformat\fR and \fBdateyesterday\fR options.
+
+.TP
+\fBnodateext\fR
+Do not archive old versions of log files with date extension
+(this overrides the \fBdateext\fR option).
+
+.TP
+\fBdateformat\fR \fIformat_string\fR
+Specify the extension for \fBdateext\fR using the notation similar to
+\fBstrftime\fR(3) function.  Only %Y %m %d %H %M %S %V and %s specifiers are
+allowed.
+The default value is \-%Y%m%d except hourly, which uses \-%Y%m%d%H as default
+value.  Note that also the character separating log name from the extension is
+part of the dateformat string.  The system clock must be set past Sep 9th 2001
+for %s to work correctly.
+Note that the datestamps generated by this format must be lexically sortable
+(that is first the year, then the month then the day.  For example 2001/12/01 is
+ok, but 01/12/2001 is not, since 01/11/2002 would sort lower while it is later).
+This is because when using the \fBrotate\fR option, \fBlogrotate\fR sorts all
+rotated filenames to find out which logfiles are older and should be removed.
+
+.TP
+\fBdateyesterday\fR
+Use yesterday's instead of today's date to create the \fBdateext\fR
+extension, so that the rotated log file has a date in its name that is
+the same as the timestamps within it.
+
+.TP
+\fBdatehourago\fR
+Use hour ago instead of current date to create the \fBdateext\fR extension,
+so that the rotated log file has a hour in its name that is the same as the
+timestamps within it.  Useful with rotate \fBhourly\fR.
+
+.SS Mail
+
+.TP
+\fBmail \fIaddress\fR
+When a log is rotated out of existence, it is mailed to \fIaddress\fR.  If
+no mail should be generated by a particular log, the \fBnomail\fR directive
+may be used.
+
+.TP
+\fBnomail\fR
+Do not mail old log files to any address.
+
+.TP
+\fBmailfirst\fR
+When using the \fBmail\fR command, mail the just-rotated file,
+instead of the about-to-expire file.
+
+.TP
+\fBmaillast\fR
+When using the \fBmail\fR command, mail the about-to-expire file,
+instead of the just-rotated file (this is the default).
+
+.SS Additional config files
+
+.TP
+\fBinclude \fIfile_or_directory\fR
+Reads the file given as an argument as if it was included inline
+where the \fBinclude\fR directive appears.  If a directory is given,
+most of the files in that directory are read in alphabetic order
+before processing of the including file continues.  The only files
+which are ignored are files which are not regular files (such as
+directories and named pipes) and files whose names end with one of
+the taboo extensions or patterns, as specified by the \fBtabooext\fR
+or \fBtaboopat\fR directives, respectively.  The given path may
+start with \fB~/\fR to make it relative to the home directory of
+the executing user.  For security reasons configuration files must
+not be group-writable nor world-writable.
+
+.SS Scripts
+
+.TP
+\fBsharedscripts\fR
+Normally, \fBprerotate\fR and \fBpostrotate\fR scripts are run for each
+log which is rotated and the absolute path to the log file is passed as first
+argument to the script.  That means a single script may be run multiple
+times for log file entries which match multiple files (such as the
+\fI/var/log/news/*\fR example).  If \fBsharedscripts\fR is specified, the
+scripts are only run once, no matter how many logs match the wildcarded pattern,
+and whole pattern is passed to them.
+However, if none of the logs in the pattern require rotating, the scripts
+will not be run at all.  If the scripts exit with error (or any log fails to
+rotate), the remaining actions will not be executed for any logs.  This option
+overrides the \fBnosharedscripts\fR option.
+
+.TP
+\fBnosharedscripts\fR
+Run \fBprerotate\fR and \fBpostrotate\fR scripts for every log file which
+is rotated (this is the default, and overrides the \fBsharedscripts\fR
+option).  The absolute path to the log file is passed as first argument
+to the script.  The absolute path to the final rotated log file is passed as
+the second argument to the \fBpostrotate\fR script.  If the scripts exit with
+error, the remaining actions will not be executed for the affected log only.
+
+.tq
+\fBfirstaction\fR
+.tq
+\ \ \ \ \fIscript\fR
+.tq
+\fBendscript\fR
+The \fIscript\fR is executed once
+before all log files that match the wildcarded pattern are rotated, before
+the prerotate script is run and only if at least one log will actually be
+rotated.  These directives may only appear inside a log file definition.
+The whole pattern is passed to the script as its first argument. If the script
+exits with an error, no further processing is done.  See also \fBlastaction\fR
+and the \fBSCRIPTS\fR section.
+
+.tq
+\fBlastaction\fR
+.tq
+\ \ \ \ \fIscript\fR
+.tq
+\fBendscript\fR
+The \fIscript\fR is executed once
+after all log files that match the wildcarded pattern are rotated, after the
+postrotate script is run and only if at least one log is rotated.  These
+directives may only appear inside a log file definition.  The whole pattern is
+passed to the script as its first argument.  If the script exits
+with an error, just an error message is shown (as this is the last
+action).  See also \fBfirstaction\fR and
+the \fBSCRIPTS\fR section.
+
+.tq
+\fBprerotate\fR
+.tq
+\ \ \ \ \fIscript\fR
+.tq
+\fBendscript\fR
+The \fIscript\fR is executed before
+the log file is rotated and only if the log will actually be rotated.  These
+directives may only appear inside a log file definition.  Normally,
+the absolute path to the log file is passed as the first argument to the script.
+If \fBsharedscripts\fR is specified, the whole pattern is passed to the script.
+See also \fBpostrotate\fR and the \fBSCRIPTS\fR section.
+See \fBsharedscripts\fR and \fBnosharedscripts\fR for error handling.
+
+.tq
+\fBpostrotate\fR
+.tq
+\ \ \ \ \fIscript\fR
+.tq
+\fBendscript\fR
+The \fIscript\fR is executed
+after the log file is rotated.  These directives may only appear inside
+a log file definition.  Normally, the absolute path to the log file is
+passed as the first argument to the script and the absolute path to the final
+rotated log file is passed as the second argument to the script.  If
+\fBsharedscripts\fR is specified, the whole pattern is passed as the first
+argument to the script, and the second argument is omitted.
+See also \fBprerotate\fR and the \fBSCRIPTS\fR section.
+See \fBsharedscripts\fR and \fBnosharedscripts\fR
+for error handling.
+
+.tq
+\fBpreremove\fR
+.tq
+\ \ \ \ \fIscript\fR
+.tq
+\fBendscript\fR
+The \fIscript\fR is executed
+once just
+before removal of a log file.  \fBlogrotate\fR will pass
+the name of file which is soon to be removed as the first argument to the
+script. See also \fBfirstaction\fR and
+the \fBSCRIPTS\fR section.
+
+.SH SCRIPTS
+
+The lines between the starting keyword (e.g. \fBprerotate\fR) and
+\fBendscript\fR (both of which must appear on lines by themselves) are
+executed (using \fB/bin/sh\fR).
+The script inherits some traits from the \fBlogrotate\fR process, including
+stderr, stdout, the current directory, the environment, and the umask.
+Scripts are run as the invoking user and group, irrespective of any \fBsu\fR
+directive.  If the \fB\-\-log\fR flag was specified, file descriptor 3 is the
+log file.
+
+.SH USER AND GROUP
+
+User and group identifiers are resolved first by trying the textual
+representation and, in case it fails, afterwards by the numeric value.
+
+.SH FILES
+
+.TS
+tab(:);
+l l l.
+\fI@STATE_FILE_PATH@\fR:Default state file.
+\fI/etc/logrotate.conf\fR:Configuration options.
+.TE
+
+
+.SH "SEE ALSO"
+
+.BR chmod (2),
+.BR gunzip (1),
+.BR gzip (1),
+.BR mail (1),
+.BR shred (1),
+.BR strftime (3),
+.BR strtoul (3),
+<https://github.com/logrotate/logrotate>
+
+.SH AUTHORS
+
+.nf
+Erik Troan, Preston Brown, Jan Kaluza.
+
+<https://github.com/logrotate/logrotate>
+
+.fi
Index: create-3.18.0-patch/logrotate-3.18.0-new
===================================================================
--- create-3.18.0-patch/logrotate-3.18.0-new	(nonexistent)
+++ create-3.18.0-patch/logrotate-3.18.0-new	(revision 5)

Property changes on: create-3.18.0-patch/logrotate-3.18.0-new
___________________________________________________________________
Added: svn:ignore
## -0,0 +1,73 ##
+
+# install dir
+dist
+
+# Target build dirs
+.a1x-newlib
+.a2x-newlib
+.at91sam7s-newlib
+
+.build-machine
+
+.a1x-glibc
+.a2x-glibc
+.h3-glibc
+.h5-glibc
+.i586-glibc
+.i686-glibc
+.imx6-glibc
+.jz47xx-glibc
+.makefile
+.am335x-glibc
+.omap543x-glibc
+.p5600-glibc
+.power8-glibc
+.power8le-glibc
+.power9-glibc
+.power9le-glibc
+.m1000-glibc
+.riscv64-glibc
+.rk328x-glibc
+.rk33xx-glibc
+.rk339x-glibc
+.s8xx-glibc
+.s9xx-glibc
+.x86_64-glibc
+
+# Hidden files (each file)
+.makefile
+.dist
+.rootfs
+
+# src & hw requires
+.src_requires
+.src_requires_depend
+.requires
+.requires_depend
+
+# Tarballs
+*.gz
+*.bz2
+*.lz
+*.xz
+*.tgz
+*.txz
+
+# Signatures
+*.asc
+*.sig
+*.sign
+*.sha1sum
+
+# Patches
+*.patch
+
+# Descriptions
+*.dsc
+*.txt
+
+# Default linux config files
+*.defconfig
+
+# backup copies
+*~
Index: create-3.18.0-patch
===================================================================
--- create-3.18.0-patch	(nonexistent)
+++ create-3.18.0-patch	(revision 5)

Property changes on: create-3.18.0-patch
___________________________________________________________________
Added: svn:ignore
## -0,0 +1,73 ##
+
+# install dir
+dist
+
+# Target build dirs
+.a1x-newlib
+.a2x-newlib
+.at91sam7s-newlib
+
+.build-machine
+
+.a1x-glibc
+.a2x-glibc
+.h3-glibc
+.h5-glibc
+.i586-glibc
+.i686-glibc
+.imx6-glibc
+.jz47xx-glibc
+.makefile
+.am335x-glibc
+.omap543x-glibc
+.p5600-glibc
+.power8-glibc
+.power8le-glibc
+.power9-glibc
+.power9le-glibc
+.m1000-glibc
+.riscv64-glibc
+.rk328x-glibc
+.rk33xx-glibc
+.rk339x-glibc
+.s8xx-glibc
+.s9xx-glibc
+.x86_64-glibc
+
+# Hidden files (each file)
+.makefile
+.dist
+.rootfs
+
+# src & hw requires
+.src_requires
+.src_requires_depend
+.requires
+.requires_depend
+
+# Tarballs
+*.gz
+*.bz2
+*.lz
+*.xz
+*.tgz
+*.txz
+
+# Signatures
+*.asc
+*.sig
+*.sign
+*.sha1sum
+
+# Patches
+*.patch
+
+# Descriptions
+*.dsc
+*.txt
+
+# Default linux config files
+*.defconfig
+
+# backup copies
+*~
Index: patches/README
===================================================================
--- patches/README	(nonexistent)
+++ patches/README	(revision 5)
@@ -0,0 +1,6 @@
+
+/* begin *
+
+   TODO: Leave some comment here.
+
+ * end */
Index: patches
===================================================================
--- patches	(nonexistent)
+++ patches	(revision 5)

Property changes on: patches
___________________________________________________________________
Added: svn:ignore
## -0,0 +1,73 ##
+
+# install dir
+dist
+
+# Target build dirs
+.a1x-newlib
+.a2x-newlib
+.at91sam7s-newlib
+
+.build-machine
+
+.a1x-glibc
+.a2x-glibc
+.h3-glibc
+.h5-glibc
+.i586-glibc
+.i686-glibc
+.imx6-glibc
+.jz47xx-glibc
+.makefile
+.am335x-glibc
+.omap543x-glibc
+.p5600-glibc
+.power8-glibc
+.power8le-glibc
+.power9-glibc
+.power9le-glibc
+.m1000-glibc
+.riscv64-glibc
+.rk328x-glibc
+.rk33xx-glibc
+.rk339x-glibc
+.s8xx-glibc
+.s9xx-glibc
+.x86_64-glibc
+
+# Hidden files (each file)
+.makefile
+.dist
+.rootfs
+
+# src & hw requires
+.src_requires
+.src_requires_depend
+.requires
+.requires_depend
+
+# Tarballs
+*.gz
+*.bz2
+*.lz
+*.xz
+*.tgz
+*.txz
+
+# Signatures
+*.asc
+*.sig
+*.sign
+*.sha1sum
+
+# Patches
+*.patch
+
+# Descriptions
+*.dsc
+*.txt
+
+# Default linux config files
+*.defconfig
+
+# backup copies
+*~
Index: .
===================================================================
--- .	(nonexistent)
+++ .	(revision 5)

Property changes on: .
___________________________________________________________________
Added: svn:ignore
## -0,0 +1,73 ##
+
+# install dir
+dist
+
+# Target build dirs
+.a1x-newlib
+.a2x-newlib
+.at91sam7s-newlib
+
+.build-machine
+
+.a1x-glibc
+.a2x-glibc
+.h3-glibc
+.h5-glibc
+.i586-glibc
+.i686-glibc
+.imx6-glibc
+.jz47xx-glibc
+.makefile
+.am335x-glibc
+.omap543x-glibc
+.p5600-glibc
+.power8-glibc
+.power8le-glibc
+.power9-glibc
+.power9le-glibc
+.m1000-glibc
+.riscv64-glibc
+.rk328x-glibc
+.rk33xx-glibc
+.rk339x-glibc
+.s8xx-glibc
+.s9xx-glibc
+.x86_64-glibc
+
+# Hidden files (each file)
+.makefile
+.dist
+.rootfs
+
+# src & hw requires
+.src_requires
+.src_requires_depend
+.requires
+.requires_depend
+
+# Tarballs
+*.gz
+*.bz2
+*.lz
+*.xz
+*.tgz
+*.txz
+
+# Signatures
+*.asc
+*.sig
+*.sign
+*.sha1sum
+
+# Patches
+*.patch
+
+# Descriptions
+*.dsc
+*.txt
+
+# Default linux config files
+*.defconfig
+
+# backup copies
+*~