~ubuntu-branches/ubuntu/trusty/logrotate/trusty

« back to all changes in this revision

Viewing changes to .pc/parser571033.patch/config.c

  • Committer: Bazaar Package Importer
  • Author(s): Paul Martin
  • Date: 2010-03-20 19:37:26 UTC
  • mto: (4.1.5 squeeze)
  • mto: This revision was merged to the branch mainline in revision 15.
  • Revision ID: james.westby@ubuntu.com-20100320193726-rca1ozk3r4l79y9u
Tags: 3.7.8-5
* New patch:
  + parser571033.patch: fix the config parser to not get confused when
    a wildcard produces no results. (Closes: 571033)
* Switch to dpkg-source 3.0 (quilt) format
* Bump debhelper version to 7 (dh_clean -k -> dh_prep).
* Update standards version to 3.8.4 (no changes).

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#include <sys/queue.h>
 
2
#include <alloca.h>
 
3
#include <ctype.h>
 
4
#include <dirent.h>
 
5
#include <errno.h>
 
6
#include <fcntl.h>
 
7
#include <glob.h>
 
8
#include <grp.h>
 
9
#include <popt.h>
 
10
#include <pwd.h>
 
11
#include <stdio.h>
 
12
#include <stdlib.h>
 
13
#include <string.h>
 
14
#include <sys/stat.h>
 
15
#include <time.h>
 
16
#include <unistd.h>
 
17
#include <assert.h>
 
18
#include <wchar.h>
 
19
#include <wctype.h>
 
20
#include <fnmatch.h>
 
21
 
 
22
#include "basenames.h"
 
23
#include "log.h"
 
24
#include "logrotate.h"
 
25
 
 
26
#if !defined(GLOB_ABORTED) && defined(GLOB_ABEND)
 
27
#define GLOB_ABORTED GLOB_ABEND
 
28
#endif
 
29
 
 
30
#define REALLOC_STEP    10
 
31
 
 
32
#if defined(SunOS) && !defined(isblank)
 
33
#define isblank(c)      ( (c) == ' ' || (c) == '\t' ) ? 1 : 0
 
34
#endif
 
35
 
 
36
static char *defTabooExts[] = { ".rpmsave", ".rpmorig", "~", ",v",
 
37
    ".disabled", ".dpkg-old", ".dpkg-dist", ".dpkg-new", ".cfsaved",
 
38
    ".rpmnew", ".swp", ".cfsaved", ".rhn-cfg-tmp-*"
 
39
};
 
40
static int defTabooCount = sizeof(defTabooExts) / sizeof(char *);
 
41
 
 
42
/* I shouldn't use globals here :-( */
 
43
static char **tabooExts = NULL;
 
44
int tabooCount = 0;
 
45
 
 
46
static int readConfigFile(const char *configFile, struct logInfo *defConfig);
 
47
static int globerr(const char *pathname, int theerr);
 
48
 
 
49
static int isolateValue(const char *fileName, int lineNum, char *key,
 
50
                        char **startPtr, char **endPtr)
 
51
{
 
52
    char *chptr = *startPtr;
 
53
 
 
54
    while (isblank(*chptr))
 
55
        chptr++;
 
56
    if (*chptr == '=') {
 
57
        chptr++;
 
58
        while (*chptr && isblank(*chptr))
 
59
            chptr++;
 
60
    }
 
61
 
 
62
    if (*chptr == '\n') {
 
63
        message(MESS_ERROR, "%s:%d argument expected after %s\n",
 
64
                fileName, lineNum, key);
 
65
        return 1;
 
66
    }
 
67
 
 
68
    *startPtr = chptr;
 
69
 
 
70
    while (*chptr != '\n')
 
71
        chptr++;
 
72
 
 
73
    while (isspace(*chptr))
 
74
        chptr--;
 
75
 
 
76
    *endPtr = chptr + 1;
 
77
 
 
78
    return 0;
 
79
}
 
80
 
 
81
static char *readPath(const char *configFile, int lineNum, char *key,
 
82
                      char **startPtr)
 
83
{
 
84
    char oldchar;
 
85
    char *endtag, *chptr;
 
86
    char *start = *startPtr;
 
87
    char *path;
 
88
 
 
89
    wchar_t pwc;
 
90
    size_t len;
 
91
 
 
92
    if (!isolateValue(configFile, lineNum, key, &start, &endtag)) {
 
93
        oldchar = *endtag, *endtag = '\0';
 
94
 
 
95
        chptr = start;
 
96
 
 
97
        while( (len = mbrtowc(&pwc, chptr, strlen(chptr), NULL)) != 0 ) {
 
98
                if( len == (size_t)(-1) || len == (size_t)(-2) || !iswprint(pwc) || iswblank(pwc) ) {
 
99
                    message(MESS_ERROR, "%s:%d bad %s path %s\n",
 
100
                            configFile, lineNum, key, start);
 
101
                    return NULL;
 
102
                }
 
103
                chptr += len;
 
104
        }
 
105
 
 
106
/*
 
107
        while (*chptr && isprint(*chptr) && *chptr != ' ')
 
108
            chptr++;
 
109
        if (*chptr) {
 
110
            message(MESS_ERROR, "%s:%d bad %s path %s\n",
 
111
                    configFile, lineNum, key, start);
 
112
            return NULL;
 
113
        }
 
114
*/
 
115
 
 
116
        path = strdup(start);
 
117
 
 
118
 
 
119
        *endtag = oldchar, start = endtag;
 
120
 
 
121
        *startPtr = start;
 
122
 
 
123
        return path;
 
124
    } else
 
125
        return NULL;
 
126
}
 
127
 
 
128
static char *readAddress(const char *configFile, int lineNum, char *key,
 
129
                         char **startPtr)
 
130
{
 
131
    char oldchar;
 
132
    char *endtag, *chptr;
 
133
    char *start = *startPtr;
 
134
    char *address;
 
135
 
 
136
    if (!isolateValue(configFile, lineNum, key, &start, &endtag)) {
 
137
        oldchar = *endtag, *endtag = '\0';
 
138
 
 
139
        chptr = start;
 
140
        while (*chptr && isprint(*chptr) && *chptr != ' ')
 
141
            chptr++;
 
142
        if (*chptr) {
 
143
            message(MESS_ERROR, "%s:%d bad %s address %s\n",
 
144
                    configFile, lineNum, key, start);
 
145
            return NULL;
 
146
        }
 
147
 
 
148
        address = strdup(start);
 
149
 
 
150
        *endtag = oldchar, start = endtag;
 
151
 
 
152
        *startPtr = start;
 
153
 
 
154
        return address;
 
155
    } else
 
156
        return NULL;
 
157
}
 
158
 
 
159
static int checkFile(const char *fname)
 
160
{
 
161
        int i;
 
162
        char pattern[PATH_MAX];
 
163
 
 
164
        /* Check if fname is '.' or '..'; if so, return false */
 
165
        if (fname[0] == '.' && (!fname[1] || (fname[1] == '.' && !fname[2])))
 
166
                return 0;
 
167
 
 
168
        /* Check if fname is ending in a taboo-extension; if so, return false */
 
169
        for (i = 0; i < tabooCount; i++) {
 
170
                snprintf(pattern, sizeof(pattern), "*%s", tabooExts[i]);
 
171
                if (!fnmatch(pattern, fname, 0))
 
172
                {
 
173
                        message(MESS_DEBUG, "Ignoring %s, because of %s ending\n",
 
174
                                        fname, tabooExts[i]);
 
175
                        return 0;
 
176
                }
 
177
        }
 
178
 
 
179
        /* All checks have been passed; return true */
 
180
        return 1;
 
181
}
 
182
 
 
183
/* Used by qsort to sort filelist */
 
184
static int compar(const void *p, const void *q)
 
185
{
 
186
    return strcoll(*((char **) p), *((char **) q));
 
187
}
 
188
 
 
189
/* Free memory blocks pointed to by pointers in a 2d array and the array itself */
 
190
static void free_2d_array(char **array, int lines_count)
 
191
{
 
192
    int i;
 
193
    for (i = 0; i < lines_count; ++i)
 
194
        free(array[i]);
 
195
    free(array);
 
196
}
 
197
 
 
198
static void copyLogInfo(struct logInfo *to, struct logInfo *from)
 
199
{
 
200
    memset(to, 0, sizeof(*to));
 
201
    if (from->oldDir)
 
202
        to->oldDir = strdup(from->oldDir);
 
203
    to->criterium = from->criterium;
 
204
    to->threshhold = from->threshhold;
 
205
    to->minsize = from->minsize;
 
206
    to->rotateCount = from->rotateCount;
 
207
    to->rotateAge = from->rotateAge;
 
208
    to->logStart = from->logStart;
 
209
    if (from->pre)
 
210
        to->pre = strdup(from->pre);
 
211
    if (from->post)
 
212
        to->post = strdup(from->post);
 
213
    if (from->first)
 
214
        to->first = strdup(from->first);
 
215
    if (from->last)
 
216
        to->last = strdup(from->last);
 
217
    if (from->logAddress)
 
218
        to->logAddress = strdup(from->logAddress);
 
219
    if (from->extension)
 
220
        to->extension = strdup(from->extension);
 
221
    if (from->compress_prog)
 
222
        to->compress_prog = strdup(from->compress_prog);
 
223
    if (from->uncompress_prog)
 
224
        to->uncompress_prog = strdup(from->uncompress_prog);
 
225
    if (from->compress_ext)
 
226
        to->compress_ext = strdup(from->compress_ext);
 
227
    to->flags = from->flags;
 
228
    to->shred_cycles = from->shred_cycles;
 
229
    to->createMode = from->createMode;
 
230
    to->createUid = from->createUid;
 
231
    to->createGid = from->createGid;
 
232
    if (from->compress_options_count) {
 
233
        poptDupArgv(from->compress_options_count, from->compress_options_list, 
 
234
                    &to->compress_options_count,  &to->compress_options_list);
 
235
    }
 
236
        if (from->dateformat)
 
237
                to->dateformat = strdup(from->dateformat);
 
238
}
 
239
 
 
240
static void freeLogInfo(struct logInfo *log)
 
241
{
 
242
        free(log->pattern);
 
243
        free_2d_array(log->files, log->numFiles);
 
244
        free(log->oldDir);
 
245
        free(log->pre);
 
246
        free(log->post);
 
247
        free(log->first);
 
248
        free(log->last);
 
249
        free(log->logAddress);
 
250
        free(log->extension);
 
251
        free(log->compress_prog);
 
252
        free(log->uncompress_prog);
 
253
        free(log->compress_ext);
 
254
        free(log->compress_options_list);
 
255
        free(log->dateformat);
 
256
}
 
257
 
 
258
static struct logInfo *newLogInfo(struct logInfo *template)
 
259
{
 
260
        struct logInfo *new;
 
261
 
 
262
        if ((new = malloc(sizeof(*new))) == NULL)
 
263
                return NULL;
 
264
 
 
265
        copyLogInfo(new, template);
 
266
        TAILQ_INSERT_TAIL(&logs, new, list);
 
267
        numLogs++;
 
268
 
 
269
        return new;
 
270
}
 
271
 
 
272
static void removeLogInfo(struct logInfo *log)
 
273
{
 
274
        if (log == NULL)
 
275
                return;
 
276
 
 
277
        freeLogInfo(log);
 
278
        TAILQ_REMOVE(&logs, log, list);
 
279
        numLogs--;
 
280
}
 
281
 
 
282
static void freeTailLogs(int num)
 
283
{
 
284
        message(MESS_DEBUG, "removing last %d log configs\n", num);
 
285
 
 
286
        while (num--)
 
287
                removeLogInfo(*(logs.tqh_last));
 
288
}
 
289
 
 
290
static int readConfigPath(const char *path, struct logInfo *defConfig)
 
291
{
 
292
    struct stat sb;
 
293
    int here, oldnumlogs, result = 1;
 
294
        struct logInfo defConfigBackup;
 
295
 
 
296
    if (stat(path, &sb)) {
 
297
        message(MESS_ERROR, "cannot stat %s: %s\n", path, strerror(errno));
 
298
        return 1;
 
299
    }
 
300
 
 
301
    if (S_ISDIR(sb.st_mode)) {
 
302
        char **namelist, **p;
 
303
        struct dirent *dp;
 
304
        int files_count, i;
 
305
        DIR *dirp;
 
306
 
 
307
        here = open(".", O_RDONLY);
 
308
 
 
309
        if ((dirp = opendir(path)) == NULL) {
 
310
            message(MESS_ERROR, "cannot open directory %s: %s\n", path,
 
311
                    strerror(errno));
 
312
            close(here);
 
313
            return 1;
 
314
        }
 
315
        files_count = 0;
 
316
        namelist = NULL;
 
317
        while ((dp = readdir(dirp)) != NULL) {
 
318
            if (checkFile(dp->d_name)) {
 
319
                /* Realloc memory for namelist array if necessary */
 
320
                if (files_count % REALLOC_STEP == 0) {
 
321
                    p = (char **) realloc(namelist,
 
322
                                          (files_count +
 
323
                                           REALLOC_STEP) * sizeof(char *));
 
324
                    if (p) {
 
325
                        namelist = p;
 
326
                        memset(namelist + files_count, '\0',
 
327
                               REALLOC_STEP * sizeof(char *));
 
328
                    } else {
 
329
                        free_2d_array(namelist, files_count);
 
330
                        closedir(dirp);
 
331
                        close(here);
 
332
                        message(MESS_ERROR, "cannot realloc: %s\n",
 
333
                                strerror(errno));
 
334
                        return 1;
 
335
                    }
 
336
                }
 
337
                /* Alloc memory for file name */
 
338
                if ((namelist[files_count] =
 
339
                     (char *) malloc(strlen(dp->d_name) + 1))) {
 
340
                    strcpy(namelist[files_count], dp->d_name);
 
341
                    files_count++;
 
342
                } else {
 
343
                    free_2d_array(namelist, files_count);
 
344
                    closedir(dirp);
 
345
                    close(here);
 
346
                    message(MESS_ERROR, "cannot realloc: %s\n",
 
347
                            strerror(errno));
 
348
                    return 1;
 
349
                }
 
350
            }
 
351
        }
 
352
        closedir(dirp);
 
353
 
 
354
        if (files_count > 0) {
 
355
            qsort(namelist, files_count, sizeof(char *), compar);
 
356
        } else {
 
357
            close(here);
 
358
            return 0;
 
359
        }
 
360
 
 
361
        if (chdir(path)) {
 
362
            message(MESS_ERROR, "error in chdir(\"%s\"): %s\n", path,
 
363
                    strerror(errno));
 
364
            close(here);
 
365
            free_2d_array(namelist, files_count);
 
366
            return 1;
 
367
        }
 
368
 
 
369
        for (i = 0; i < files_count; ++i) {
 
370
            assert(namelist[i] != NULL);
 
371
            oldnumlogs = numLogs;
 
372
            copyLogInfo(&defConfigBackup, defConfig);
 
373
            if (readConfigFile(namelist[i], defConfig)) {
 
374
                message(MESS_ERROR, "found error in file %s, skipping\n", namelist[i]);
 
375
                freeTailLogs(numLogs - oldnumlogs);
 
376
                freeLogInfo(defConfig);
 
377
                copyLogInfo(defConfig, &defConfigBackup);
 
378
                freeLogInfo(&defConfigBackup);
 
379
                continue;
 
380
            } else {
 
381
                result = 0;
 
382
            }
 
383
            freeLogInfo(&defConfigBackup);
 
384
        }
 
385
 
 
386
        if (fchdir(here) < 0) {
 
387
                message(MESS_ERROR, "could not change directory to '.'");
 
388
        }
 
389
        close(here);
 
390
        free_2d_array(namelist, files_count);
 
391
    } else {
 
392
        oldnumlogs = numLogs;
 
393
        copyLogInfo(&defConfigBackup, defConfig);
 
394
        if (readConfigFile(path, defConfig)) {
 
395
            freeTailLogs(numLogs - oldnumlogs);
 
396
            freeLogInfo(defConfig);
 
397
            copyLogInfo(defConfig, &defConfigBackup);
 
398
        } else {
 
399
            result = 0;
 
400
        }
 
401
        freeLogInfo(&defConfigBackup);
 
402
    }
 
403
 
 
404
    return result;
 
405
}
 
406
 
 
407
int readAllConfigPaths(const char **paths)
 
408
{
 
409
    int i, result = 0;
 
410
    const char **file;
 
411
    struct logInfo defConfig = {
 
412
                .pattern = NULL,
 
413
                .files = NULL,
 
414
                .numFiles = 0,
 
415
                .oldDir = NULL,
 
416
                .criterium = ROT_SIZE,
 
417
                .threshhold = 1024 * 1024,
 
418
                .minsize = 0,
 
419
                .rotateCount = 0,
 
420
                .rotateAge = 0,
 
421
                .logStart = -1,
 
422
                .pre = NULL,
 
423
                .post = NULL,
 
424
                .first = NULL,
 
425
                .last = NULL,
 
426
                .logAddress = NULL,
 
427
                .extension = NULL,
 
428
                .compress_prog = NULL,
 
429
                .uncompress_prog = NULL,
 
430
                .compress_ext = NULL,
 
431
                .dateformat = NULL,
 
432
                .flags = LOG_FLAG_IFEMPTY,
 
433
                .shred_cycles = 0,
 
434
                .createMode = NO_MODE,
 
435
                .createUid = NO_UID,
 
436
                .createGid = NO_GID,
 
437
                .compress_options_list = NULL,
 
438
                .compress_options_count = 0
 
439
    };
 
440
 
 
441
    tabooExts = malloc(sizeof(*tabooExts) * defTabooCount);
 
442
    for (i = 0; i < defTabooCount; i++) {
 
443
        if ((tabooExts[i] = (char *) malloc(strlen(defTabooExts[i]) + 1))) {
 
444
            strcpy(tabooExts[i], defTabooExts[i]);
 
445
            tabooCount++;
 
446
        } else {
 
447
            free_2d_array(tabooExts, tabooCount);
 
448
            message(MESS_ERROR, "cannot malloc: %s\n", strerror(errno));
 
449
            return 1;
 
450
        }
 
451
    }
 
452
 
 
453
    for (file = paths; *file; file++) {
 
454
        if (readConfigPath(*file, &defConfig)) {
 
455
            result = 1;
 
456
            break;
 
457
        }
 
458
    }
 
459
    free_2d_array(tabooExts, tabooCount);
 
460
    freeLogInfo(&defConfig);
 
461
    return result;
 
462
}
 
463
 
 
464
static int globerr(const char *pathname, int theerr)
 
465
{
 
466
    message(MESS_ERROR, "error accessing %s: %s\n", pathname,
 
467
            strerror(theerr));
 
468
 
 
469
    /* We want the glob operation to abort on error, so return 1 */
 
470
    return 1;
 
471
}
 
472
 
 
473
#define freeLogItem(what) \
 
474
        do { \
 
475
                free(newlog->what); \
 
476
                newlog->what = NULL; \
 
477
        } while (0);
 
478
#define MAX_NESTING 16U
 
479
 
 
480
static int readConfigFile(const char *configFile, struct logInfo *defConfig)
 
481
{
 
482
    int fd;
 
483
    char *buf, *endtag;
 
484
    char oldchar, foo;
 
485
    off_t length;
 
486
    int lineNum = 1;
 
487
    int multiplier;
 
488
    int i, k;
 
489
    char *scriptStart = NULL;
 
490
    char **scriptDest = NULL;
 
491
    struct logInfo *newlog = defConfig;
 
492
    char *start, *chptr;
 
493
    char *dirName;
 
494
    struct group *group;
 
495
    struct passwd *pw;
 
496
    int rc;
 
497
    char createOwner[200], createGroup[200];
 
498
    int createMode;
 
499
    struct stat sb, sb2;
 
500
    glob_t globResult;
 
501
    const char **argv;
 
502
    int argc, argNum;
 
503
    int logerror = 0;
 
504
    struct logInfo *log;
 
505
        static unsigned recursion_depth = 0U;
 
506
 
 
507
    /* FIXME: createOwner and createGroup probably shouldn't be fixed
 
508
       length arrays -- of course, if we aren't run setuid it doesn't
 
509
       matter much */
 
510
 
 
511
    fd = open(configFile, O_RDONLY);
 
512
    if (fd < 0) {
 
513
        message(MESS_ERROR, "failed to open config file %s: %s\n",
 
514
                configFile, strerror(errno));
 
515
        return 1;
 
516
    }
 
517
 
 
518
    if (fstat(fd, &sb)) {
 
519
        message(MESS_ERROR, "fstat of %s failed: %s\n", configFile,
 
520
                strerror(errno));
 
521
        close(fd);
 
522
        return 1;
 
523
    }
 
524
    if (!S_ISREG(sb.st_mode)) {
 
525
        message(MESS_DEBUG,
 
526
                "Ignoring %s because it's not a regular file.\n",
 
527
                configFile);
 
528
        close(fd);
 
529
        return 0;
 
530
    }
 
531
 
 
532
    length = sb.st_size;
 
533
 
 
534
    if (length > 0xffffff) {
 
535
        message(MESS_ERROR, "file %s too large, probably not a config file.\n",
 
536
                configFile);
 
537
        close(fd);
 
538
        return 1;
 
539
    }    
 
540
 
 
541
    buf = alloca(length + 2);
 
542
    if (!buf) {
 
543
        message(MESS_ERROR, "alloca() of %d bytes failed\n", (int) length);
 
544
        close(fd);
 
545
        return 1;
 
546
    }
 
547
 
 
548
    if (read(fd, buf, length) != length) {
 
549
        message(MESS_ERROR, "failed to read %s: %s\n", configFile,
 
550
                strerror(errno));
 
551
        close(fd);
 
552
        return 1;
 
553
    }
 
554
 
 
555
    close(fd);
 
556
 
 
557
    /* knowing the buffer ends with a newline makes things (a bit) cleaner */
 
558
    buf[length + 1] = '\0';
 
559
    buf[length] = '\n';
 
560
 
 
561
    message(MESS_DEBUG, "reading config file %s\n", configFile);
 
562
 
 
563
    start = buf;
 
564
    while (*start) {
 
565
        if (logerror) {
 
566
            assert(newlog != defConfig);
 
567
 
 
568
            message(MESS_ERROR, "found error in %s, skipping\n",
 
569
                    newlog->pattern ? newlog->pattern : "log config");
 
570
 
 
571
            while (*start != '}') {
 
572
                if (*start == 0) {
 
573
                    message(MESS_ERROR, "%s:%d } expected \n",
 
574
                            configFile, lineNum);
 
575
                    return 1;
 
576
                } else if (*start == '\n') {
 
577
                    lineNum++;
 
578
                }
 
579
                start++;
 
580
            }
 
581
            start++;
 
582
 
 
583
            freeTailLogs(1);
 
584
            newlog = defConfig;
 
585
            logerror = 0;
 
586
        }                               
 
587
        while (isblank(*start) && (*start))
 
588
            start++;
 
589
        if (*start == '#') {
 
590
            while (*start != '\n')
 
591
                start++;
 
592
        }
 
593
 
 
594
        if (*start == '\n') {
 
595
            start++;
 
596
            lineNum++;
 
597
            continue;
 
598
        }
 
599
 
 
600
        if (scriptStart) {
 
601
            if (!strncmp(start, "endscript", 9)) {
 
602
                chptr = start + 9;
 
603
                while (isblank(*chptr))
 
604
                    chptr++;
 
605
                if (*chptr == '\n') {
 
606
                    endtag = start;
 
607
                    while (*endtag != '\n')
 
608
                        endtag--;
 
609
                    endtag++;
 
610
                    *scriptDest = malloc(endtag - scriptStart + 1);
 
611
                    strncpy(*scriptDest, scriptStart,
 
612
                            endtag - scriptStart);
 
613
                    (*scriptDest)[endtag - scriptStart] = '\0';
 
614
                    start = chptr + 1;
 
615
                    lineNum++;
 
616
 
 
617
                    scriptDest = NULL;
 
618
                    scriptStart = NULL;
 
619
                }
 
620
            }
 
621
 
 
622
            if (scriptStart) {
 
623
                while (*start != '\n')
 
624
                    start++;
 
625
                lineNum++;
 
626
                start++;
 
627
            }
 
628
        } else if (isalpha(*start)) {
 
629
            endtag = start;
 
630
            while (isalpha(*endtag))
 
631
                endtag++;
 
632
            oldchar = *endtag;
 
633
            *endtag = '\0';
 
634
 
 
635
            if (!strcmp(start, "compress")) {
 
636
                newlog->flags |= LOG_FLAG_COMPRESS;
 
637
 
 
638
                *endtag = oldchar, start = endtag;
 
639
            } else if (!strcmp(start, "nocompress")) {
 
640
                newlog->flags &= ~LOG_FLAG_COMPRESS;
 
641
 
 
642
                *endtag = oldchar, start = endtag;
 
643
            } else if (!strcmp(start, "delaycompress")) {
 
644
                newlog->flags |= LOG_FLAG_DELAYCOMPRESS;
 
645
 
 
646
                *endtag = oldchar, start = endtag;
 
647
            } else if (!strcmp(start, "nodelaycompress")) {
 
648
                newlog->flags &= ~LOG_FLAG_DELAYCOMPRESS;
 
649
 
 
650
                *endtag = oldchar, start = endtag;
 
651
                } else if (!strcmp(start, "shred")) {
 
652
                newlog->flags |= LOG_FLAG_SHRED;
 
653
 
 
654
                *endtag = oldchar, start = endtag;
 
655
                } else if (!strcmp(start, "noshred")) { 
 
656
                newlog->flags &= ~LOG_FLAG_SHRED;
 
657
 
 
658
                *endtag = oldchar, start = endtag;
 
659
            } else if (!strcmp(start, "sharedscripts")) {
 
660
                newlog->flags |= LOG_FLAG_SHAREDSCRIPTS;
 
661
 
 
662
                *endtag = oldchar, start = endtag;
 
663
            } else if (!strcmp(start, "nosharedscripts")) {
 
664
                newlog->flags &= ~LOG_FLAG_SHAREDSCRIPTS;
 
665
 
 
666
                *endtag = oldchar, start = endtag;
 
667
            } else if (!strcmp(start, "copytruncate")) {
 
668
                newlog->flags |= LOG_FLAG_COPYTRUNCATE;
 
669
 
 
670
                *endtag = oldchar, start = endtag;
 
671
            } else if (!strcmp(start, "nocopytruncate")) {
 
672
                newlog->flags &= ~LOG_FLAG_COPYTRUNCATE;
 
673
 
 
674
                *endtag = oldchar, start = endtag;
 
675
            } else if (!strcmp(start, "copy")) {
 
676
                newlog->flags |= LOG_FLAG_COPY;
 
677
 
 
678
                *endtag = oldchar, start = endtag;
 
679
            } else if (!strcmp(start, "nocopy")) {
 
680
                newlog->flags &= ~LOG_FLAG_COPY;
 
681
 
 
682
                *endtag = oldchar, start = endtag;
 
683
            } else if (!strcmp(start, "ifempty")) {
 
684
                newlog->flags |= LOG_FLAG_IFEMPTY;
 
685
 
 
686
                *endtag = oldchar, start = endtag;
 
687
            } else if (!strcmp(start, "notifempty")) {
 
688
                newlog->flags &= ~LOG_FLAG_IFEMPTY;
 
689
 
 
690
                *endtag = oldchar, start = endtag;
 
691
            } else if (!strcmp(start, "dateext")) {
 
692
                newlog->flags |= LOG_FLAG_DATEEXT;
 
693
 
 
694
                *endtag = oldchar, start = endtag;
 
695
            } else if (!strcmp(start, "nodateext")) {
 
696
                newlog->flags &= ~LOG_FLAG_DATEEXT;
 
697
                
 
698
                *endtag = oldchar, start = endtag;
 
699
            } else if (!strcmp(start, "dateformat")) {
 
700
                *endtag = oldchar, start = endtag;
 
701
                
 
702
                endtag = start;
 
703
                while (*endtag != '\n')
 
704
                    endtag++;
 
705
                while (isspace(*endtag))
 
706
                    endtag--;
 
707
                endtag++;
 
708
                oldchar = *endtag, *endtag = '\0';
 
709
 
 
710
                freeLogItem(dateformat);
 
711
                newlog->dateformat = strdup(start);
 
712
 
 
713
                *endtag = oldchar, start = endtag;
 
714
            } else if (!strcmp(start, "noolddir")) {
 
715
                newlog->oldDir = NULL;
 
716
 
 
717
                *endtag = oldchar, start = endtag;
 
718
            } else if (!strcmp(start, "mailfirst")) {
 
719
                newlog->flags |= LOG_FLAG_MAILFIRST;
 
720
 
 
721
                *endtag = oldchar, start = endtag;
 
722
            } else if (!strcmp(start, "maillast")) {
 
723
                newlog->flags &= ~LOG_FLAG_MAILFIRST;
 
724
 
 
725
                *endtag = oldchar, start = endtag;
 
726
            } else if (!strcmp(start, "create")) {
 
727
                *endtag = oldchar, start = endtag;
 
728
 
 
729
                endtag = start;
 
730
                while (*endtag != '\n')
 
731
                    endtag++;
 
732
                while (isspace(*endtag))
 
733
                    endtag--;
 
734
                endtag++;
 
735
                oldchar = *endtag, *endtag = '\0';
 
736
 
 
737
                rc = sscanf(start, "%o %s %s%c", &createMode,
 
738
                            createOwner, createGroup, &foo);
 
739
                if (rc == 4) {
 
740
                    message(MESS_ERROR, "%s:%d extra arguments for "
 
741
                            "create\n", configFile, lineNum);
 
742
                    if (newlog != defConfig) {
 
743
                        *endtag = oldchar, start = endtag;
 
744
                        logerror = 1;
 
745
                        continue;
 
746
                    } else {
 
747
                        return 1;
 
748
                    }
 
749
                }
 
750
 
 
751
                if (rc > 0)
 
752
                    newlog->createMode = createMode;
 
753
 
 
754
                if (rc > 1) {
 
755
                    pw = getpwnam(createOwner);
 
756
                    if (!pw) {
 
757
                        message(MESS_ERROR, "%s:%d unknown user '%s'\n",
 
758
                                configFile, lineNum, createOwner);
 
759
                        if (newlog != defConfig) {
 
760
                            *endtag = oldchar, start = endtag;
 
761
                            logerror = 1;
 
762
                            continue;
 
763
                        } else {
 
764
                            return 1;
 
765
                        }
 
766
                    }
 
767
                    newlog->createUid = pw->pw_uid;
 
768
                    endpwent();
 
769
                }
 
770
                if (rc > 2) {
 
771
                    group = getgrnam(createGroup);
 
772
                    if (!group) {
 
773
                        message(MESS_ERROR, "%s:%d unknown group '%s'\n",
 
774
                                configFile, lineNum, createGroup);
 
775
                        if (newlog != defConfig) {
 
776
                            *endtag = oldchar, start = endtag;
 
777
                            logerror = 1;
 
778
                            continue;
 
779
                        } else {
 
780
                            return 1;
 
781
                        }
 
782
                    }
 
783
                    newlog->createGid = group->gr_gid;
 
784
                    endgrent();
 
785
                }
 
786
 
 
787
                newlog->flags |= LOG_FLAG_CREATE;
 
788
 
 
789
                *endtag = oldchar, start = endtag;
 
790
            } else if (!strcmp(start, "nocreate")) {
 
791
                newlog->flags &= ~LOG_FLAG_CREATE;
 
792
 
 
793
                *endtag = oldchar, start = endtag;
 
794
            } else if (!strcmp(start, "size") || !strcmp(start, "minsize")) {
 
795
                unsigned int size = 0;
 
796
                char *opt = start;
 
797
                *endtag = oldchar, start = endtag;
 
798
 
 
799
                if (!isolateValue(configFile, lineNum, opt, &start,
 
800
                                  &endtag)) {
 
801
                    oldchar = *endtag, *endtag = '\0';
 
802
 
 
803
                    length = strlen(start) - 1;
 
804
                    if (start[length] == 'k') {
 
805
                        start[length] = '\0';
 
806
                        multiplier = 1024;
 
807
                    } else if (start[length] == 'M') {
 
808
                        start[length] = '\0';
 
809
                        multiplier = 1024 * 1024;
 
810
                    } else if (start[length] == 'G') {
 
811
                        start[length] = '\0';
 
812
                        multiplier = 1024 * 1024 * 1024;
 
813
                    } else if (!isdigit(start[length])) {
 
814
                        message(MESS_ERROR, "%s:%d unknown unit '%c'\n",
 
815
                                configFile, lineNum, start[length]);
 
816
                        if (newlog != defConfig) {
 
817
                            *endtag = oldchar, start = endtag;
 
818
                            logerror = 1;
 
819
                            continue;
 
820
                        } else {
 
821
                            return 1;
 
822
                        }
 
823
                    } else {
 
824
                        multiplier = 1;
 
825
                    }
 
826
 
 
827
                    size = multiplier * strtoul(start, &chptr, 0);
 
828
                    if (*chptr) {
 
829
                        message(MESS_ERROR, "%s:%d bad size '%s'\n",
 
830
                                configFile, lineNum, start);
 
831
                        if (newlog != defConfig) {
 
832
                            *endtag = oldchar, start = endtag;
 
833
                            logerror = 1;
 
834
                            continue;
 
835
                        } else {
 
836
                            return 1;
 
837
                        }
 
838
                    }
 
839
 
 
840
                    if (!strncmp(opt, "size", 4)) {
 
841
                        newlog->criterium = ROT_SIZE;
 
842
                        newlog->threshhold = size;
 
843
                    } else
 
844
                        newlog->minsize = size;
 
845
 
 
846
                    *endtag = oldchar, start = endtag;
 
847
                }
 
848
#if 0                           /* this seems like such a good idea :-( */
 
849
            } else if (!strcmp(start, "days")) {
 
850
                *endtag = oldchar, start = endtag;
 
851
 
 
852
                if (!isolateValue(configFile, lineNum, "size", &start,
 
853
                                  &endtag)) {
 
854
                    oldchar = *endtag, *endtag = '\0';
 
855
 
 
856
                    newlog->threshhold = strtoul(start, &chptr, 0);
 
857
                    if (*chptr) {
 
858
                        message(MESS_ERROR,
 
859
                                "%s:%d bad number of days'%s'\n",
 
860
                                configFile, lineNum, start);
 
861
                        return 1;
 
862
                    }
 
863
 
 
864
                    newlog->criterium = ROT_DAYS;
 
865
 
 
866
                    *endtag = oldchar, start = endtag;
 
867
                }
 
868
#endif
 
869
            } else if (!strcmp(start, "shredcycles")) {
 
870
                *endtag = oldchar, start = endtag;
 
871
 
 
872
                if (!isolateValue(configFile, lineNum, "shred cycles", 
 
873
                                &start, &endtag)) {
 
874
                        oldchar = *endtag, *endtag = '\0';
 
875
 
 
876
                        newlog->shred_cycles = strtoul(start, &chptr, 0);
 
877
                        if (*chptr || newlog->shred_cycles < 0) {
 
878
                                message(MESS_ERROR, "%s:%d bad shred cycles '%s'\n",
 
879
                                                configFile, lineNum, start);
 
880
                                return 1;
 
881
                        }
 
882
                        *endtag = oldchar, start = endtag;
 
883
                }
 
884
                } else if (!strcmp(start, "daily")) {
 
885
                *endtag = oldchar, start = endtag;
 
886
 
 
887
                newlog->criterium = ROT_DAYS;
 
888
                newlog->threshhold = 1;
 
889
            } else if (!strcmp(start, "monthly")) {
 
890
                *endtag = oldchar, start = endtag;
 
891
 
 
892
                newlog->criterium = ROT_MONTHLY;
 
893
            } else if (!strcmp(start, "weekly")) {
 
894
                *endtag = oldchar, start = endtag;
 
895
 
 
896
                newlog->criterium = ROT_WEEKLY;
 
897
            } else if (!strcmp(start, "yearly")) {
 
898
                *endtag = oldchar, start = endtag;
 
899
 
 
900
                newlog->criterium = ROT_YEARLY;
 
901
            } else if (!strcmp(start, "rotate")) {
 
902
                *endtag = oldchar, start = endtag;
 
903
 
 
904
                if (!isolateValue
 
905
                    (configFile, lineNum, "rotate count", &start,
 
906
                     &endtag)) {
 
907
                    oldchar = *endtag, *endtag = '\0';
 
908
 
 
909
                    newlog->rotateCount = strtoul(start, &chptr, 0);
 
910
                    if (*chptr || newlog->rotateCount < 0) {
 
911
                        message(MESS_ERROR,
 
912
                                "%s:%d bad rotation count '%s'\n",
 
913
                                configFile, lineNum, start);
 
914
                        if (newlog != defConfig) {
 
915
                            *endtag = oldchar, start = endtag;
 
916
                            logerror = 1;
 
917
                            continue;
 
918
                        } else {
 
919
                            return 1;
 
920
                        }
 
921
                    }
 
922
                    *endtag = oldchar, start = endtag;
 
923
                }
 
924
            } else if (!strcmp(start, "start")) {
 
925
                *endtag = oldchar, start = endtag;
 
926
 
 
927
                if (!isolateValue
 
928
                    (configFile, lineNum, "start count", &start,
 
929
                     &endtag)) {
 
930
                    oldchar = *endtag, *endtag = '\0';
 
931
 
 
932
                    newlog->logStart = strtoul(start, &chptr, 0);
 
933
                    if (*chptr || newlog->logStart < 0) {
 
934
                        message(MESS_ERROR, "%s:%d bad start count '%s'\n",
 
935
                                configFile, lineNum, start);
 
936
                        if (newlog != defConfig) {
 
937
                            *endtag = oldchar, start = endtag;
 
938
                            logerror = 1;
 
939
                            continue;
 
940
                        } else {
 
941
                            return 1;
 
942
                        }
 
943
                    }
 
944
                    *endtag = oldchar, start = endtag;
 
945
                }
 
946
            } else if (!strcmp(start, "maxage")) {
 
947
                *endtag = oldchar, start = endtag;
 
948
 
 
949
                if (!isolateValue
 
950
                    (configFile, lineNum, "maxage count", &start,
 
951
                     &endtag)) {
 
952
                    oldchar = *endtag, *endtag = '\0';
 
953
 
 
954
                    newlog->rotateAge = strtoul(start, &chptr, 0);
 
955
                    if (*chptr || newlog->rotateAge < 0) {
 
956
                        message(MESS_ERROR, "%s:%d bad maximum age '%s'\n",
 
957
                                configFile, lineNum, start);
 
958
                        if (newlog != defConfig) {
 
959
                            *endtag = oldchar, start = endtag;
 
960
                            logerror = 1;
 
961
                            continue;
 
962
                        } else {
 
963
                            return 1;
 
964
                        }
 
965
                    }
 
966
                    *endtag = oldchar, start = endtag;
 
967
                }
 
968
            } else if (!strcmp(start, "errors")) {
 
969
                message(MESS_DEBUG,
 
970
                        "%s: %d: the errors directive is deprecated and no longer used.\n",
 
971
                        configFile, lineNum);
 
972
            } else if (!strcmp(start, "mail")) {
 
973
                *endtag = oldchar, start = endtag;
 
974
                freeLogItem(logAddress);
 
975
                if (!(newlog->logAddress = readAddress(configFile, lineNum,
 
976
                                                       "mail", &start))) {
 
977
                    if (newlog != defConfig) {
 
978
                        logerror = 1;
 
979
                        continue;
 
980
                    } else {
 
981
                        return 1;
 
982
                    }
 
983
                }
 
984
            } else if (!strcmp(start, "nomail")) {
 
985
                freeLogItem(logAddress);
 
986
 
 
987
                *endtag = oldchar, start = endtag;
 
988
            } else if (!strcmp(start, "missingok")) {
 
989
                newlog->flags |= LOG_FLAG_MISSINGOK;
 
990
 
 
991
                *endtag = oldchar, start = endtag;
 
992
            } else if (!strcmp(start, "nomissingok")) {
 
993
                newlog->flags &= ~LOG_FLAG_MISSINGOK;
 
994
 
 
995
                *endtag = oldchar, start = endtag;
 
996
            } else if (!strcmp(start, "prerotate")) {
 
997
                *endtag = oldchar, start = endtag;
 
998
 
 
999
                freeLogItem (pre);
 
1000
 
 
1001
                scriptStart = start;
 
1002
                scriptDest = &newlog->pre;
 
1003
 
 
1004
                while (*start != '\n')
 
1005
                    start++;
 
1006
            } else if (!strcmp(start, "firstaction")) {
 
1007
                *endtag = oldchar, start = endtag;
 
1008
 
 
1009
                freeLogItem (first);
 
1010
 
 
1011
                scriptStart = start;
 
1012
                scriptDest = &newlog->first;
 
1013
 
 
1014
                while (*start != '\n')
 
1015
                    start++;
 
1016
            } else if (!strcmp(start, "postrotate")) {
 
1017
                *endtag = oldchar, start = endtag;
 
1018
 
 
1019
                freeLogItem (post);
 
1020
 
 
1021
                scriptStart = start;
 
1022
                scriptDest = &newlog->post;
 
1023
 
 
1024
                while (*start != '\n')
 
1025
                    start++;
 
1026
            } else if (!strcmp(start, "lastaction")) {
 
1027
                *endtag = oldchar, start = endtag;
 
1028
 
 
1029
                freeLogItem (last);
 
1030
 
 
1031
                scriptStart = start;
 
1032
                scriptDest = &newlog->last;
 
1033
 
 
1034
                while (*start != '\n')
 
1035
                    start++;
 
1036
            } else if (!strcmp(start, "tabooext")) {
 
1037
                if (newlog != defConfig) {
 
1038
                    message(MESS_ERROR,
 
1039
                            "%s:%d tabooext may not appear inside "
 
1040
                            "of log file definition\n", configFile,
 
1041
                            lineNum);
 
1042
                    *endtag = oldchar, start = endtag;
 
1043
                    logerror = 1;
 
1044
                    continue;
 
1045
                }
 
1046
 
 
1047
                *endtag = oldchar, start = endtag;
 
1048
                if (!isolateValue(configFile, lineNum, "tabooext", &start,
 
1049
                                  &endtag)) {
 
1050
                    oldchar = *endtag, *endtag = '\0';
 
1051
 
 
1052
                    if (*start == '+') {
 
1053
                        start++;
 
1054
                        while (isspace(*start) && *start)
 
1055
                            start++;
 
1056
                    } else {
 
1057
                        free_2d_array(tabooExts, tabooCount);
 
1058
                        tabooCount = 0;
 
1059
                        tabooExts = malloc(1);
 
1060
                    }
 
1061
 
 
1062
                    while (*start) {
 
1063
                        chptr = start;
 
1064
                        while (!isspace(*chptr) && /* *chptr != ',' && */ *chptr)
 
1065
                            chptr++;
 
1066
 
 
1067
                        tabooExts = realloc(tabooExts, sizeof(*tabooExts) *
 
1068
                                            (tabooCount + 1));
 
1069
                        tabooExts[tabooCount] = malloc(chptr - start + 1);
 
1070
                        strncpy(tabooExts[tabooCount], start,
 
1071
                                chptr - start);
 
1072
                        tabooExts[tabooCount][chptr - start] = '\0';
 
1073
                        tabooCount++;
 
1074
 
 
1075
                        start = chptr;
 
1076
                        /*
 
1077
                        if (*start == ',')
 
1078
                            start++;
 
1079
                        */
 
1080
                        while (isspace(*start) && *start)
 
1081
                            start++;
 
1082
                    }
 
1083
 
 
1084
                    *endtag = oldchar, start = endtag;
 
1085
                }
 
1086
            } else if (!strcmp(start, "include")) {
 
1087
                if (newlog != defConfig) {
 
1088
                    message(MESS_ERROR,
 
1089
                            "%s:%d include may not appear inside "
 
1090
                            "of log file definition\n", configFile,
 
1091
                            lineNum);
 
1092
                    *endtag = oldchar, start = endtag;
 
1093
                    logerror = 1;
 
1094
                    continue;
 
1095
                }
 
1096
 
 
1097
                *endtag = oldchar, start = endtag;
 
1098
                if (!isolateValue(configFile, lineNum, "include", &start,
 
1099
                                  &endtag)) {
 
1100
                    oldchar = *endtag, *endtag = '\0';
 
1101
 
 
1102
                    message(MESS_DEBUG, "including %s\n", start);
 
1103
                        if (++recursion_depth > MAX_NESTING) {
 
1104
                                message(MESS_ERROR, "%s:%d include nesting too deep\n",
 
1105
                                                configFile, lineNum);
 
1106
                                --recursion_depth;
 
1107
                                return 1;
 
1108
                        }
 
1109
                    if (readConfigPath(start, defConfig)) {
 
1110
                                --recursion_depth;
 
1111
                                return 1;
 
1112
                        }
 
1113
                        --recursion_depth;
 
1114
 
 
1115
                    *endtag = oldchar, start = endtag;
 
1116
                }
 
1117
            } else if (!strcmp(start, "olddir")) {
 
1118
                *endtag = oldchar, start = endtag;
 
1119
 
 
1120
                freeLogItem (oldDir);
 
1121
 
 
1122
                if (!(newlog->oldDir = readPath(configFile, lineNum,
 
1123
                                                "olddir", &start))) {
 
1124
                    if (newlog != defConfig) {
 
1125
                        logerror = 1;
 
1126
                        continue;
 
1127
                    } else {
 
1128
                        return 1;
 
1129
                    }
 
1130
                }
 
1131
#if 0
 
1132
                if (stat(newlog->oldDir, &sb)) {
 
1133
                    message(MESS_ERROR, "%s:%d error verifying olddir "
 
1134
                            "path %s: %s\n", configFile, lineNum,
 
1135
                            newlog->oldDir, strerror(errno));
 
1136
                    free(newlog->oldDir);
 
1137
                    return 1;
 
1138
                }
 
1139
 
 
1140
                if (!S_ISDIR(sb.st_mode)) {
 
1141
                    message(MESS_ERROR, "%s:%d olddir path %s is not a "
 
1142
                            "directory\n", configFile, lineNum,
 
1143
                            newlog->oldDir);
 
1144
                    free(newlog->oldDir);
 
1145
                    return 1;
 
1146
                }
 
1147
#endif
 
1148
 
 
1149
                message(MESS_DEBUG, "olddir is now %s\n", newlog->oldDir);
 
1150
            } else if (!strcmp(start, "extension")) {
 
1151
                *endtag = oldchar, start = endtag;
 
1152
 
 
1153
                if (!isolateValue
 
1154
                    (configFile, lineNum, "extension name", &start,
 
1155
                     &endtag)) {
 
1156
                    oldchar = *endtag, *endtag = '\0';
 
1157
 
 
1158
                    freeLogItem (extension);
 
1159
                    newlog->extension = strdup(start);
 
1160
 
 
1161
                    *endtag = oldchar, start = endtag;
 
1162
                }
 
1163
 
 
1164
                message(MESS_DEBUG, "extension is now %s\n",
 
1165
                        newlog->extension);
 
1166
 
 
1167
            } else if (!strcmp(start, "compresscmd")) {
 
1168
                *endtag = oldchar, start = endtag;
 
1169
 
 
1170
                freeLogItem (compress_prog);
 
1171
 
 
1172
                if (!
 
1173
                    (newlog->compress_prog =
 
1174
                     readPath(configFile, lineNum, "compress", &start))) {
 
1175
                    if (newlog != defConfig) {
 
1176
                        logerror = 1;
 
1177
                        continue;
 
1178
                    } else {
 
1179
                        return 1;
 
1180
                    }
 
1181
                }
 
1182
 
 
1183
                if (access(newlog->compress_prog, X_OK)) {
 
1184
                    message(MESS_ERROR,
 
1185
                            "%s:%d compression program %s is not an executable file\n",
 
1186
                            configFile, lineNum, newlog->compress_prog);
 
1187
                    if (newlog != defConfig) {
 
1188
                        logerror = 1;
 
1189
                        continue;
 
1190
                    } else {
 
1191
                        return 1;
 
1192
                    }
 
1193
                }
 
1194
 
 
1195
                message(MESS_DEBUG, "compress_prog is now %s\n",
 
1196
                        newlog->compress_prog);
 
1197
 
 
1198
            } else if (!strcmp(start, "uncompresscmd")) {
 
1199
                *endtag = oldchar, start = endtag;
 
1200
 
 
1201
                freeLogItem (uncompress_prog);
 
1202
 
 
1203
                if (!
 
1204
                    (newlog->uncompress_prog =
 
1205
                     readPath(configFile, lineNum, "uncompress",
 
1206
                              &start))) {
 
1207
                    if (newlog != defConfig) {
 
1208
                        logerror = 1;
 
1209
                        continue;
 
1210
                    } else {
 
1211
                        return 1;
 
1212
                    }
 
1213
                }
 
1214
 
 
1215
                if (access(newlog->uncompress_prog, X_OK)) {
 
1216
                    message(MESS_ERROR,
 
1217
                            "%s:%d uncompression program %s is not an executable file\n",
 
1218
                            configFile, lineNum, newlog->uncompress_prog);
 
1219
                    if (newlog != defConfig) {
 
1220
                        logerror = 1;
 
1221
                        continue;
 
1222
                    } else {
 
1223
                        return 1;
 
1224
                    }
 
1225
                }
 
1226
 
 
1227
                message(MESS_DEBUG, "uncompress_prog is now %s\n",
 
1228
                        newlog->uncompress_prog);
 
1229
 
 
1230
            } else if (!strcmp(start, "compressoptions")) {
 
1231
                char *options;
 
1232
 
 
1233
                if (newlog->compress_options_list) {
 
1234
                    free(newlog->compress_options_list);
 
1235
                    newlog->compress_options_list = NULL;
 
1236
                    newlog->compress_options_count = 0;
 
1237
                }
 
1238
 
 
1239
                *endtag = oldchar, start = endtag;
 
1240
                if (!
 
1241
                    (options =
 
1242
                     readPath(configFile, lineNum, "compressoptions",
 
1243
                              &start))) {
 
1244
                    if (newlog != defConfig) {
 
1245
                        logerror = 1;
 
1246
                        continue;
 
1247
                    } else {
 
1248
                        return 1;
 
1249
                    }
 
1250
                }
 
1251
 
 
1252
                if (poptParseArgvString(options,
 
1253
                                        &newlog->compress_options_count,
 
1254
                                        &newlog->compress_options_list)) {
 
1255
                    message(MESS_ERROR,
 
1256
                            "%s:%d invalid compression options\n",
 
1257
                            configFile, lineNum);
 
1258
                    free(options);
 
1259
                    if (newlog != defConfig) {
 
1260
                        logerror = 1;
 
1261
                        continue;
 
1262
                    } else {
 
1263
                        return 1;
 
1264
                    }
 
1265
                }
 
1266
 
 
1267
                message(MESS_DEBUG, "compress_options is now %s\n",
 
1268
                        options);
 
1269
                free(options);
 
1270
            } else if (!strcmp(start, "compressext")) {
 
1271
                *endtag = oldchar, start = endtag;
 
1272
 
 
1273
                freeLogItem (compress_ext);
 
1274
 
 
1275
                if (!
 
1276
                    (newlog->compress_ext =
 
1277
                     readPath(configFile, lineNum, "compress-ext",
 
1278
                              &start))) {
 
1279
                    if (newlog != defConfig) {
 
1280
                        logerror = 1;
 
1281
                        continue;
 
1282
                    } else {
 
1283
                        return 1;
 
1284
                    }
 
1285
                }
 
1286
 
 
1287
                message(MESS_DEBUG, "compress_ext is now %s\n",
 
1288
                        newlog->compress_ext);
 
1289
            } else {
 
1290
                message(MESS_ERROR, "%s:%d unknown option '%s' "
 
1291
                        "-- ignoring line\n", configFile, lineNum, start);
 
1292
 
 
1293
                *endtag = oldchar, start = endtag;
 
1294
            }
 
1295
 
 
1296
            while (isblank(*start))
 
1297
                start++;
 
1298
 
 
1299
            if (*start != '\n') {
 
1300
                message(MESS_ERROR, "%s:%d unexpected text\n", configFile,
 
1301
                        lineNum);
 
1302
                while (*start != '\n')
 
1303
                    start++;
 
1304
            }
 
1305
 
 
1306
            lineNum++;
 
1307
            start++;
 
1308
        } else if (*start == '/' || *start == '"' || *start == '\'') {
 
1309
            if (newlog != defConfig) {
 
1310
                message(MESS_ERROR, "%s:%d unexpected log filename\n",
 
1311
                        configFile, lineNum);
 
1312
                logerror = 1;
 
1313
                continue;
 
1314
            }
 
1315
 
 
1316
            /* If no compression options were found in config file, set
 
1317
               default values */
 
1318
            if (!newlog->compress_prog)
 
1319
                newlog->compress_prog = strdup(COMPRESS_COMMAND);
 
1320
            if (!newlog->uncompress_prog)
 
1321
                newlog->uncompress_prog = strdup(UNCOMPRESS_COMMAND);
 
1322
            if (!newlog->compress_ext)
 
1323
                newlog->compress_ext = strdup(COMPRESS_EXT);
 
1324
 
 
1325
            /* Allocate a new logInfo structure and insert it into the logs
 
1326
               queue, copying the actual values from defConfig */
 
1327
            if ((newlog = newLogInfo(defConfig)) == NULL)
 
1328
                return 1;
 
1329
 
 
1330
            endtag = start;
 
1331
            while (*endtag != '{' && *endtag != '\0')
 
1332
                endtag++;
 
1333
            if (*endtag != '{') {
 
1334
                message(MESS_ERROR, "%s:%d missing end of line\n",
 
1335
                        configFile, lineNum);
 
1336
            }
 
1337
            *endtag = '\0';
 
1338
 
 
1339
            if (poptParseArgvString(start, &argc, &argv)) {
 
1340
                message(MESS_ERROR, "%s:%d error parsing filename\n",
 
1341
                        configFile, lineNum);
 
1342
                return 1;
 
1343
            } else if (argc < 1) {
 
1344
                message(MESS_ERROR,
 
1345
                        "%s:%d { expected after log file name(s)\n",
 
1346
                        configFile, lineNum);
 
1347
                return 1;
 
1348
            }
 
1349
 
 
1350
            newlog->files = NULL;
 
1351
            newlog->numFiles = 0;
 
1352
            for (argNum = 0; argNum < argc && logerror != 1; argNum++) {
 
1353
                rc = glob(argv[argNum], GLOB_NOCHECK, globerr,
 
1354
                          &globResult);
 
1355
                if (rc == GLOB_ABORTED) {
 
1356
                    if (newlog->flags & LOG_FLAG_MISSINGOK)
 
1357
                        continue;
 
1358
 
 
1359
                    message(MESS_ERROR, "%s:%d glob failed for %s\n",
 
1360
                            configFile, lineNum, argv[argNum]);
 
1361
                    logerror = 1;
 
1362
                    break;
 
1363
                }
 
1364
 
 
1365
                newlog->files =
 
1366
                    realloc(newlog->files,
 
1367
                            sizeof(*newlog->files) * (newlog->numFiles +
 
1368
                                                      globResult.
 
1369
                                                      gl_pathc));
 
1370
 
 
1371
                for (i = 0; i < globResult.gl_pathc; i++) {
 
1372
                    /* if we glob directories we can get false matches */
 
1373
                    if (!lstat(globResult.gl_pathv[i], &sb) &&
 
1374
                        S_ISDIR(sb.st_mode))
 
1375
                        continue;
 
1376
 
 
1377
                    for (log = logs.tqh_first; log != NULL;
 
1378
                                log = log->list.tqe_next) {
 
1379
                        for (k = 0; k < log->numFiles; k++) {
 
1380
                            if (!strcmp(log->files[k],
 
1381
                                        globResult.gl_pathv[i])) {
 
1382
                                message(MESS_ERROR,
 
1383
                                        "%s:%d duplicate log entry for %s\n",
 
1384
                                        configFile, lineNum,
 
1385
                                        globResult.gl_pathv[i]);
 
1386
                                logerror = 1;
 
1387
                                goto duperror;
 
1388
                            }
 
1389
                        }
 
1390
                    }
 
1391
 
 
1392
                    newlog->files[newlog->numFiles] =
 
1393
                        strdup(globResult.gl_pathv[i]);
 
1394
                    newlog->numFiles++;
 
1395
                }
 
1396
duperror:
 
1397
                globfree(&globResult);
 
1398
            }
 
1399
 
 
1400
            newlog->pattern = strdup(start);
 
1401
 
 
1402
            if (!logerror)
 
1403
                message(MESS_DEBUG, "reading config info for %s\n", start);
 
1404
 
 
1405
            free(argv);
 
1406
 
 
1407
            start = endtag + 1;
 
1408
        } else if (*start == '}') {
 
1409
            if (newlog == defConfig) {
 
1410
                message(MESS_ERROR, "%s:%d unexpected }\n", configFile,
 
1411
                        lineNum);
 
1412
                return 1;
 
1413
            }
 
1414
 
 
1415
            if (newlog->oldDir) {
 
1416
                for (i = 0; i < newlog->numFiles; i++) {
 
1417
                    char *ld;
 
1418
                    dirName = ourDirName(newlog->files[i]);
 
1419
                    if (stat(dirName, &sb2)) {
 
1420
                        message(MESS_ERROR,
 
1421
                                "%s:%d error verifying log file "
 
1422
                                "path %s: %s\n", configFile, lineNum,
 
1423
                                dirName, strerror(errno));
 
1424
                        free(dirName);
 
1425
                        return 1;
 
1426
                    }
 
1427
                    ld = alloca(strlen(dirName) + strlen(newlog->oldDir) +
 
1428
                                2);
 
1429
                    sprintf(ld, "%s/%s", dirName, newlog->oldDir);
 
1430
                    free(dirName);
 
1431
 
 
1432
                    if (newlog->oldDir[0] != '/')
 
1433
                        dirName = ld;
 
1434
                    else
 
1435
                        dirName = newlog->oldDir;
 
1436
                    if (stat(dirName, &sb)) {
 
1437
                        message(MESS_ERROR, "%s:%d error verifying olddir "
 
1438
                                "path %s: %s\n", configFile, lineNum,
 
1439
                                dirName, strerror(errno));
 
1440
                        return 1;
 
1441
                    }
 
1442
 
 
1443
                    if (sb.st_dev != sb2.st_dev) {
 
1444
                        message(MESS_ERROR,
 
1445
                                "%s:%d olddir %s and log file %s "
 
1446
                                "are on different devices\n", configFile,
 
1447
                                lineNum, newlog->oldDir, newlog->files[i]);
 
1448
                        return 1;
 
1449
                    }
 
1450
                }
 
1451
            }
 
1452
 
 
1453
            newlog = defConfig;
 
1454
 
 
1455
            start++;
 
1456
            while (isblank(*start))
 
1457
                start++;
 
1458
 
 
1459
            if (*start != '\n') {
 
1460
                message(MESS_ERROR, "%s:%d, unexpected text after {\n",
 
1461
                        configFile, lineNum);
 
1462
            }
 
1463
        } else {
 
1464
            message(MESS_ERROR, "%s:%d lines must begin with a keyword "
 
1465
                    "or a filename (possibly in double quotes)\n",
 
1466
                    configFile, lineNum);
 
1467
 
 
1468
            while (*start != '\n')
 
1469
                start++;
 
1470
            lineNum++;
 
1471
            start++;
 
1472
        }
 
1473
    }
 
1474
 
 
1475
    if (scriptStart) {
 
1476
        message(MESS_ERROR,
 
1477
                "%s:prerotate or postrotate without endscript\n",
 
1478
                configFile);
 
1479
        return 1;
 
1480
    }
 
1481
 
 
1482
    return 0;
 
1483
}