~davewalker/ubuntu/lucid/logrotate/sync_3.7.8-5

« back to all changes in this revision

Viewing changes to .pc/copyloginfo-512152.patch/config.c

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