~ubuntu-branches/ubuntu/dapper/syslog-ng/dapper

« back to all changes in this revision

Viewing changes to src/affile.c

  • Committer: Bazaar Package Importer
  • Author(s): Magosányi Árpád (mag)
  • Date: 2004-03-13 18:35:37 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20040313183537-g0fsc2j2y1wbxage
Tags: 1.6.2-3
* changed manpage to better reflect -v. Closes: #228377
* fixed build-depends, hopefully correctly now:( Closes: #237668

Show diffs side-by-side

added added

removed removed

Lines of Context:
19
19
 *
20
20
 * Inspired by nsyslog, originally written by Darren Reed.
21
21
 *
22
 
 * $Id: affile.c,v 1.46 2002/02/06 15:20:39 bazsi Exp $
 
22
 * $Id: affile.c,v 1.61.4.1 2004/01/13 18:08:02 bazsi Exp $
23
23
 *
24
24
 ***************************************************************************/
 
25
 
 
26
/*
 
27
 * Several patches to the macro expansion function were contributed
 
28
 * by Gert Menke.
 
29
 *
 
30
 * Portions Copyright (c) 2002 by Gert Menke
 
31
 * All rights reserved.
 
32
 *
 
33
 * Redistribution and use in source and binary forms, with or without
 
34
 * modification, are permitted provided that the following conditions
 
35
 * are met:
 
36
 * 1. Redistributions of source code must retain the above copyright
 
37
 *    notice, this list of conditions and the following disclaimer.
 
38
 * 2. Redistributions in binary form must reproduce the above copyright
 
39
 *    notice, this list of conditions and the following disclaimer in the
 
40
 *    documentation and/or other materials provided with the distribution.
 
41
 * 3. Neither the name of the author nor the names of its contributors
 
42
 *    may be used to endorse or promote products derived from this software
 
43
 *    without specific prior written permission.
 
44
 *
 
45
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS `AS IS'' AND
 
46
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 
47
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 
48
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 
49
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 
50
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 
51
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 
52
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 
53
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 
54
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 
55
 * SUCH DAMAGE.
 
56
 */
25
57
 
26
58
#include "affile.h"
27
59
#include "format.h"
31
63
#include "center.h"
32
64
#include "resource.h"
33
65
#include "cfgfile.h"
 
66
#include "macros.h"
34
67
 
35
68
#include <sys/types.h>
36
69
#include <sys/stat.h>
41
74
#include <pwd.h>
42
75
#include <grp.h>
43
76
#include <unistd.h>
 
77
#include <arpa/inet.h>
 
78
#include <time.h>
44
79
#include <stdio.h>
45
 
#include <arpa/inet.h>
46
 
#include <time.h>
47
80
#include "syslog-names.h"
48
81
 
49
82
#include "affile.c.x"
53
86
#include <netinet/in.h>
54
87
#include <arpa/inet.h>
55
88
 
56
 
struct ol_string *
57
 
expand_macros(struct syslog_config *cfg, struct ol_string *template, int template_escape, struct log_info *msg);
58
 
 
59
89
 
60
90
static int do_open_file(struct ol_string *name, int flags, 
61
91
                        int uid, int gid, int mode, 
62
92
                        int dir_uid, int dir_gid, int dir_mode,
63
93
                        int create_dirs, int *fd)
64
94
{
65
 
        if (strstr(name->data, "../") ||
66
 
            strstr(name->data, "/..")) {
 
95
        if (strstr((char *) name->data, "../") ||
 
96
            strstr((char *) name->data, "/..")) {
67
97
                werror("Spurious path %S, logfile not created\n", name);
68
98
                return 0;
69
99
        }
 
100
        if (strncmp((char *) name->data, "/dev", 4) == 0) {
 
101
                werror("Changing permissions on special file %S\n", name);
 
102
        }
70
103
 
71
 
        *fd = open(name->data, flags, mode != -1 ? mode : 0600);
 
104
        *fd = open((char *) name->data, flags, mode != -1 ? mode : 0600);
72
105
        if (create_dirs && *fd == -1 && errno == ENOENT) {
73
106
                /* directory does not exist */
74
 
                char *p = name->data + 1;
 
107
                char *p = (char *) name->data + 1;
75
108
 
76
109
                p = strchr(p, '/');
77
110
                while (p) {
78
111
                        struct stat st;
79
112
                        *p = 0;
80
 
                        if (stat(name->data, &st) == 0) {
 
113
                        if (stat((char *) name->data, &st) == 0) {
81
114
                                if (!S_ISDIR(st.st_mode))
82
115
                                        return 0;
83
116
                        }
84
117
                        else if (errno == ENOENT) {
85
 
                                if (mkdir(name->data, dir_mode != -1 ? dir_mode : 0700) == -1)
 
118
                                if (mkdir((char *) name->data, dir_mode != -1 ? dir_mode : 0700) == -1)
86
119
                                        return 0;
87
120
                                if (dir_uid != -1 || dir_gid != -1)
88
 
                                        chown(name->data, dir_uid, dir_gid);
 
121
                                        chown((char *) name->data, dir_uid, dir_gid);
89
122
                                if (dir_mode != -1)
90
 
                                        chmod(name->data, dir_mode);
 
123
                                        chmod((char *) name->data, dir_mode);
91
124
                        }
92
125
                        *p = '/';
93
126
                        p = strchr(p + 1, '/');
94
127
                }
95
 
                *fd = open(name->data, flags, mode);
 
128
                *fd = open((char *) name->data, flags, mode);
96
129
        }
97
130
        if (uid != -1 || gid != -1)
98
 
                chown(name->data, uid, gid);
 
131
                chown((char *) name->data, uid, gid);
99
132
        if (mode != -1)
100
 
                chmod(name->data, mode);
 
133
                chmod((char *) name->data, mode);
101
134
        return *fd != -1;
102
135
}
103
136
 
106
139
     (name affile_source)
107
140
     (super log_source_driver)
108
141
     (vars
109
 
       (res pointer "struct resource_node")
110
142
       (flags . UINT32)
111
143
       (src object io_fd)
 
144
       (prefix pointer UINT8)
 
145
       (pad_size . UINT32)
112
146
       (name string)))
113
147
*/
114
148
 
119
153
        int fd, flags;
120
154
  
121
155
        if (self->flags & AFFILE_PIPE)
122
 
                flags = O_RDWR | O_NOCTTY | O_NONBLOCK;
 
156
                flags = O_RDWR | O_NOCTTY | O_NONBLOCK | O_LARGEFILE;
123
157
        else
124
 
                flags = O_RDONLY | O_NOCTTY | O_NONBLOCK;
 
158
                flags = O_RDONLY | O_NOCTTY | O_NONBLOCK | O_LARGEFILE;
125
159
        if (do_open_file(self->name, flags, -1, -1, -1, -1, -1, -1, 0, &fd)) {
 
160
                io_set_nonblocking(fd);
126
161
                lseek(fd, 0, SEEK_END);
127
162
                self->src = io_read(make_io_fd(cfg->backend, fd, ol_string_use(self->name)), 
128
 
                        make_log_reader(0, c), 
 
163
                        make_log_reader(0, self->prefix, cfg->log_msg_size, self->pad_size, cfg->check_hostname ? LF_CHECK_HOSTNAME : 0, cfg->bad_hostname, c), 
129
164
                        NULL);
130
 
                self->res = REMEMBER_RESOURCE(cfg->resources, &self->src->super.super);
 
165
                REMEMBER_RESOURCE(cfg->resources, &self->src->super.super);
131
166
                return ST_OK | ST_GOON;
132
167
        }
133
168
        else {
146
181
static void do_destroy_affile_source(struct log_handler *c, struct syslog_config *cfg, struct persistent_config *persist)
147
182
{
148
183
        CAST(affile_source, self, c);
149
 
        if (self->res)
150
 
                KILL_RESOURCE_NODE(cfg->resources, self->res);
 
184
        if (self->src) {
 
185
                /* KILL_RESOURCE_NODE(cfg->resources, self->res);*/ 
 
186
                closekill_fd(&self->src->super, 0);
 
187
        }
151
188
}
152
189
 
153
 
struct log_source_driver *make_affile_source(const char *name, int flags)
 
190
struct log_source_driver *make_affile_source(const char *name, int flags, UINT8 *prefix, UINT32 pad_size)
154
191
{
155
192
        NEW(affile_source, self);
156
193
  
159
196
        self->super.super.super.destroy = do_destroy_affile_source;
160
197
        self->name = c_format_cstring("%z", name);
161
198
        self->flags = flags;
 
199
        self->prefix = prefix;
 
200
        self->pad_size = pad_size;
162
201
        return &self->super;
163
202
}
164
203
 
223
262
        int fd, flags;
224
263
        
225
264
        if (self->owner->flags & AFFILE_PIPE)
226
 
                flags = O_RDWR | O_NOCTTY | O_NONBLOCK;
 
265
                flags = O_RDWR | O_NOCTTY | O_NONBLOCK | O_LARGEFILE;
227
266
        else
228
 
                flags = O_WRONLY | O_CREAT | O_APPEND | O_NOCTTY | O_NONBLOCK;
 
267
                flags = O_WRONLY | O_CREAT | O_APPEND | O_NOCTTY | O_NONBLOCK | O_LARGEFILE;
229
268
 
230
269
        if (self->owner->remove_if_older > 0) {
231
270
                /* remove (=unlink) if file is more than XXX days old */
232
271
                struct stat st;
233
272
                time_t now = time(NULL);
234
273
 
235
 
                if (stat(self->expanded_fname->data, &st) == 0) {
 
274
                if (stat((char *) self->expanded_fname->data, &st) == 0) {
236
275
                        if ((now-st.st_mtime) >= ((self->owner->remove_if_older))) {
237
 
                                unlink(self->expanded_fname->data);
 
276
                                unlink((char *) self->expanded_fname->data);
238
277
                        }
239
278
                }  
240
279
        }
249
288
                        io_write(make_io_fd(cfg->backend, fd, ol_string_use(self->expanded_fname)), 
250
289
                                 make_pkt_buffer_ext(self->owner->sync_freq, 
251
290
                                                     MAX(self->owner->super.log_fifo_size + 1, 
252
 
                                                         self->owner->sync_freq)),
 
291
                                                         self->owner->sync_freq),
 
292
                                                     !!(self->owner->flags & AFFILE_PIPE)),
253
293
                                 NULL);
254
294
                if (self->owner->flags & AFFILE_FSYNC)
255
295
                        self->dest->fsync = 1;
275
315
        CAST(affile_dest_writer, self, c);
276
316
 
277
317
        if (self->dest) {
278
 
                struct ol_string *l;
279
 
                if (self->owner->template_output)
280
 
                        l = expand_macros(self->owner->cfg, self->owner->template_output, self->owner->template_escape, msg);
281
 
                else
282
 
                        l = c_format("%S %S %S\n", msg->date, msg->host, msg->msg);
283
 
                A_WRITE_STRING(&self->dest->buffer->super, l);
 
318
                struct ol_string *msg_line;
 
319
 
 
320
                if (self->owner->template_output) {
 
321
                        msg_line = expand_macros(
 
322
                                           self->owner->cfg,
 
323
                                           self->owner->template_output,
 
324
                                           self->owner->template_escape, msg);
 
325
                } else {
 
326
                        msg_line = c_format("%S %S %S\n",
 
327
                                            msg->date,
 
328
                                            msg->host, msg->msg);
 
329
                }
 
330
                A_WRITE_STRING(&self->dest->buffer->super, msg_line);
284
331
                if (self->reap)
285
332
                        io_callout_set_timeout(self->reap, self->time_reap);
286
333
        }
311
358
         (dir_perm . int)
312
359
         (flags simple int)
313
360
         (remove_if_older . int)
314
 
         (sync_freq simple UINT32)
 
361
         (sync_freq . int)
315
362
         (template_fname string)
316
363
         (template_output string)
317
364
         (template_escape . int)
376
423
void affile_set_perm(struct log_dest_driver *c, int perm)
377
424
{
378
425
        CAST(affile_dest, self, c);
 
426
        if( perm == 01000 )
 
427
                perm=-1;
 
428
 
379
429
 
380
430
        self->perm = perm;
381
431
}
445
495
}
446
496
 
447
497
 
448
 
 
449
 
#define MAX_MACRO_ARGS        32
450
 
#define MAX_EXPANDED_MACRO    2048
451
 
 
452
 
struct macro_def {
453
 
        char *name;
454
 
        int id;
455
 
};
456
 
 
457
 
#define M_FACILITY 0
458
 
#define M_LEVEL    1
459
 
#define M_TAG      2
460
 
 
461
 
#define M_DATE     3
462
 
#define M_FULLDATE 4
463
 
#define M_ISODATE  5
464
 
#define M_YEAR     6
465
 
#define M_MONTH    7
466
 
#define M_DAY      8
467
 
#define M_HOUR     9
468
 
#define M_MIN      10
469
 
#define M_SEC      11
470
 
#define M_WEEKDAY  12
471
 
 
472
 
#define M_DATE_RECVD     13
473
 
#define M_FULLDATE_RECVD 14
474
 
#define M_ISODATE_RECVD  15
475
 
#define M_YEAR_RECVD     16
476
 
#define M_MONTH_RECVD    17
477
 
#define M_DAY_RECVD      18
478
 
#define M_HOUR_RECVD     19
479
 
#define M_MIN_RECVD      20
480
 
#define M_SEC_RECVD      21
481
 
#define M_WEEKDAY_RECVD  22
482
 
 
483
 
#define M_DATE_STAMP     23
484
 
#define M_FULLDATE_STAMP 24
485
 
#define M_ISODATE_STAMP  25
486
 
#define M_YEAR_STAMP     26
487
 
#define M_MONTH_STAMP    27
488
 
#define M_DAY_STAMP      28
489
 
#define M_HOUR_STAMP     29
490
 
#define M_MIN_STAMP      30
491
 
#define M_SEC_STAMP      31
492
 
#define M_WEEKDAY_STAMP  32
493
 
 
494
 
#define M_FULLHOST 33
495
 
#define M_HOST     34
496
 
#define M_PROGRAM  35
497
 
 
498
 
#define M_MESSAGE  36
499
 
 
500
 
#define M_SOURCE_IP 37
501
 
 
502
 
int append_string(char **dest, int *left, char *str, int length, int escape)
503
 
{
504
 
        int l;
505
 
  
506
 
        if (!escape) {
507
 
                l = MIN(length, *left - 1);
508
 
                strncpy(*dest, str, l);
509
 
        }
510
 
        else {
511
 
                char *p;
512
 
      
513
 
                l = 0;
514
 
                for (p = str; length && ((*left - l) > 1); p++, length--, l++) {
515
 
                        if (*p == '\'' || *p == '\"' || *p == '\\') {
516
 
                                if ((*left - l) < 3)
517
 
                                        break;
518
 
                                *(*dest + l) = '\\';
519
 
                                *(*dest + l + 1) = *p;
520
 
                                l++;
521
 
                        }
522
 
                        else {
523
 
                                *(*dest + l) = *p;
524
 
                        }
525
 
                }
526
 
        }
527
 
        return l;
528
 
}
529
 
 
530
 
void expand_macro(struct syslog_config *cfg, int id, int escape, char **dest, int *left, struct log_info *msg)
531
 
{
532
 
        int length = 0;
533
 
        
534
 
        switch (id) {
535
 
        case M_FACILITY: {
536
 
                /* facility */
537
 
                char *n = syslog_lookup_value(msg->pri & LOG_FACMASK, sl_facilities);
538
 
                if (n) {
539
 
                        length = append_string(dest, left, n, strlen(n), 0);
540
 
                }
541
 
                else {
542
 
                        length = snprintf(*dest, *left, "%x", (msg->pri & LOG_FACMASK) >> 3);
543
 
                }
544
 
                break;
545
 
        }
546
 
        case M_LEVEL: {
547
 
                /* level */
548
 
                char *n = syslog_lookup_value(msg->pri & LOG_PRIMASK, sl_levels);
549
 
                if (n) {
550
 
                        length = append_string(dest, left, n, strlen(n), 0);
551
 
                }
552
 
                else {
553
 
                        /* should never happen */
554
 
                        length = snprintf(*dest, *left, "%d", msg->pri & LOG_PRIMASK);
555
 
                }
556
 
 
557
 
                break;
558
 
        }
559
 
        case M_TAG: {
560
 
                length = snprintf(*dest, *left, "%02x", msg->pri);
561
 
                break;
562
 
        }
563
 
        case M_FULLHOST: {
564
 
                /* full hostname */
565
 
                length = append_string(dest, left, msg->host->data, msg->host->length, escape);
566
 
                break;
567
 
        }
568
 
        case M_SOURCE_IP: {
569
 
                char *ip;
570
 
                
571
 
                if (msg->saddr) {
572
 
                        CAST(inet_address_info, addr, msg->saddr);
573
 
                
574
 
                        ip = inet_ntoa(addr->sa.sin_addr);
575
 
                }
576
 
                else {
577
 
                        ip = "127.0.0.1";
578
 
                }
579
 
                length = append_string(dest, left, ip, strlen(ip), escape);
580
 
                break;
581
 
        }
582
 
        case M_HOST: {
583
 
                /* host */
584
 
                UINT8 *p1 = memchr(msg->host->data, '@', msg->host->length);
585
 
                UINT8 *p2;
586
 
                int remaining;
587
 
                
588
 
                if (p1) 
589
 
                        p1++; 
590
 
                else 
591
 
                        p1 = msg->host->data;
592
 
                remaining = msg->host->length - (p1 - msg->host->data);
593
 
                p2 = memchr(p1, '/', remaining);
594
 
                if (p2) {
595
 
                        length = MIN(p2 - p1, *left);
596
 
                }
597
 
                else {
598
 
                        length = MIN(*left, msg->host->length - (p1 - msg->host->data));
599
 
                }
600
 
                length = append_string(dest, left, p1, length, escape);
601
 
                break;
602
 
        }
603
 
        case M_PROGRAM: {
604
 
                /* program */
605
 
                if (msg->program) {
606
 
                        length = append_string(dest, left, msg->program->data, msg->program->length, escape);
607
 
                }
608
 
                break;
609
 
        }
610
 
        case M_FULLDATE_RECVD:
611
 
        case M_ISODATE_RECVD:
612
 
        case M_WEEKDAY_RECVD:
613
 
        case M_DATE_RECVD:
614
 
        case M_YEAR_RECVD:
615
 
        case M_MONTH_RECVD:
616
 
        case M_DAY_RECVD:
617
 
        case M_HOUR_RECVD:
618
 
        case M_MIN_RECVD:
619
 
        case M_SEC_RECVD:
620
 
 
621
 
        case M_FULLDATE_STAMP:
622
 
        case M_ISODATE_STAMP:
623
 
        case M_WEEKDAY_STAMP:
624
 
        case M_DATE_STAMP:
625
 
        case M_YEAR_STAMP:
626
 
        case M_MONTH_STAMP:
627
 
        case M_DAY_STAMP:
628
 
        case M_HOUR_STAMP:
629
 
        case M_MIN_STAMP:
630
 
        case M_SEC_STAMP:
631
 
 
632
 
        case M_FULLDATE:
633
 
        case M_ISODATE:
634
 
        case M_WEEKDAY:
635
 
        case M_DATE:
636
 
        case M_YEAR:
637
 
        case M_MONTH:
638
 
        case M_DAY: 
639
 
        case M_HOUR:
640
 
        case M_MIN:
641
 
        case M_SEC: {
642
 
                /* year, month, day */
643
 
                struct tm *tm;
644
 
 
645
 
                switch(id) {
646
 
                case M_FULLDATE_RECVD:
647
 
                case M_ISODATE_RECVD: 
648
 
                case M_WEEKDAY_RECVD: 
649
 
                case M_DATE_RECVD:    
650
 
                case M_YEAR_RECVD:    
651
 
                case M_MONTH_RECVD:   
652
 
                case M_DAY_RECVD:     
653
 
                case M_HOUR_RECVD:    
654
 
                case M_MIN_RECVD:     
655
 
                case M_SEC_RECVD:     
656
 
                        tm = localtime(&msg->recvd);
657
 
                        break;
658
 
                case M_FULLDATE_STAMP:
659
 
                case M_ISODATE_STAMP: 
660
 
                case M_WEEKDAY_STAMP: 
661
 
                case M_DATE_STAMP:    
662
 
                case M_YEAR_STAMP:    
663
 
                case M_MONTH_STAMP:   
664
 
                case M_DAY_STAMP:     
665
 
                case M_HOUR_STAMP:    
666
 
                case M_MIN_STAMP:     
667
 
                case M_SEC_STAMP:     
668
 
                        tm = localtime(&msg->stamp);
669
 
                        break;
670
 
                default:
671
 
                        if (cfg->use_time_recvd)
672
 
                                tm = localtime(&msg->recvd);
673
 
                        else
674
 
                                tm = localtime(&msg->stamp);
675
 
                        break;
676
 
                }
677
 
                
678
 
                switch (id) {
679
 
                case M_WEEKDAY:
680
 
                case M_WEEKDAY_RECVD:
681
 
                case M_WEEKDAY_STAMP:
682
 
                        length = strftime(*dest, *left - 1, "%a", tm);                  
683
 
                        break;
684
 
                case M_YEAR:
685
 
                case M_YEAR_RECVD:
686
 
                case M_YEAR_STAMP:
687
 
                        length = snprintf(*dest, *left, "%04d", tm->tm_year + 1900);
688
 
                        break;
689
 
                case M_MONTH:
690
 
                case M_MONTH_RECVD:
691
 
                case M_MONTH_STAMP:
692
 
                        length = snprintf(*dest, *left, "%02d", tm->tm_mon + 1);
693
 
                        break;
694
 
                case M_DAY:
695
 
                case M_DAY_RECVD:
696
 
                case M_DAY_STAMP:  
697
 
                        length = snprintf(*dest, *left, "%02d", tm->tm_mday);
698
 
                        break;
699
 
                case M_HOUR:
700
 
                case M_HOUR_RECVD:
701
 
                case M_HOUR_STAMP:
702
 
                        length = snprintf(*dest, *left, "%02d", tm->tm_hour);
703
 
                        break;
704
 
                case M_MIN:
705
 
                case M_MIN_RECVD:
706
 
                case M_MIN_STAMP:
707
 
                        length = snprintf(*dest, *left, "%02d", tm->tm_min);
708
 
                        break;
709
 
                case M_SEC:
710
 
                case M_SEC_RECVD:
711
 
                case M_SEC_STAMP:
712
 
                        length = snprintf(*dest, *left, "%02d", tm->tm_sec);
713
 
                        break;
714
 
                case M_ISODATE:
715
 
                case M_ISODATE_RECVD:
716
 
                case M_ISODATE_STAMP:
717
 
                        length = strftime(*dest, *left - 1, "%Y-%m-%dT%H:%M:%S%z", tm);
718
 
                        break;
719
 
                case M_FULLDATE:
720
 
                case M_FULLDATE_RECVD:
721
 
                case M_FULLDATE_STAMP:
722
 
                        length = strftime(*dest, *left - 1, "%Y %h %e %H:%M:%S", tm);
723
 
                        break;
724
 
                case M_DATE:
725
 
                case M_DATE_RECVD:
726
 
                case M_DATE_STAMP:
727
 
                        length = strftime(*dest, *left - 1, "%h %e %H:%M:%S", tm);
728
 
                        break;
729
 
                }
730
 
                break;
731
 
        }
732
 
        case M_MESSAGE: {
733
 
                /* message */
734
 
                length = append_string(dest, left, msg->msg->data, msg->msg->length, escape);
735
 
                break;
736
 
        }
737
 
        default:
738
 
                break;
739
 
        }
740
 
        *left -= length;
741
 
        *dest += length;
742
 
}
743
 
 
744
 
struct ol_string *
745
 
expand_macros(struct syslog_config *cfg, struct ol_string *template, int template_escape, struct log_info *msg)
746
 
{
747
 
        static struct macro_def macros[] = {
748
 
                { "FACILITY", M_FACILITY },
749
 
                { "PRIORITY", M_LEVEL },
750
 
                { "LEVEL", M_LEVEL },
751
 
                { "TAG", M_TAG },
752
 
 
753
 
                { "DATE", M_DATE },
754
 
                { "FULLDATE", M_FULLDATE },
755
 
                { "ISODATE", M_ISODATE },
756
 
                { "YEAR", M_YEAR },
757
 
                { "MONTH", M_MONTH },
758
 
                { "DAY", M_DAY },
759
 
                { "HOUR", M_HOUR },
760
 
                { "MIN", M_MIN },
761
 
                { "SEC", M_SEC },
762
 
                { "WEEKDAY", M_WEEKDAY },
763
 
 
764
 
                { "R_DATE", M_DATE_RECVD },
765
 
                { "R_FULLDATE", M_FULLDATE_RECVD },
766
 
                { "R_ISODATE", M_ISODATE_RECVD },
767
 
                { "R_YEAR", M_YEAR_RECVD },
768
 
                { "R_MONTH", M_MONTH_RECVD },
769
 
                { "R_DAY", M_DAY_RECVD },
770
 
                { "R_HOUR", M_HOUR_RECVD },
771
 
                { "R_MIN", M_MIN_RECVD },
772
 
                { "R_SEC", M_SEC_RECVD },
773
 
                { "R_WEEKDAY", M_WEEKDAY_RECVD },
774
 
 
775
 
                { "S_DATE", M_DATE_STAMP },
776
 
                { "S_FULLDATE", M_FULLDATE_STAMP },
777
 
                { "S_ISODATE", M_ISODATE_STAMP },
778
 
                { "S_YEAR", M_YEAR_STAMP },
779
 
                { "S_MONTH", M_MONTH_STAMP },
780
 
                { "S_DAY", M_DAY_STAMP },
781
 
                { "S_HOUR", M_HOUR_STAMP },
782
 
                { "S_MIN", M_MIN_STAMP },
783
 
                { "S_SEC", M_SEC_STAMP },
784
 
                { "S_WEEKDAY", M_WEEKDAY_STAMP },
785
 
                
786
 
                { "HOST", M_HOST },
787
 
                { "FULLHOST", M_FULLHOST },
788
 
 
789
 
                { "PROGRAM", M_PROGRAM },
790
 
                { "MSG", M_MESSAGE },
791
 
                { "MESSAGE", M_MESSAGE },
792
 
                { "SOURCEIP", M_SOURCE_IP }
793
 
        };
794
 
        char format[MAX_EXPANDED_MACRO], *format_ptr = format;
795
 
        int left = sizeof(format);
796
 
        int i, j;
797
 
 
798
 
        i = 0;
799
 
        while (left && (i < template->length)) {
800
 
 
801
 
                if (template->data[i] == '$') {
802
 
                        /* beginning of a macro */
803
 
                        for (j = 0; j < (sizeof(macros) / sizeof(struct macro_def)); j++) {
804
 
                                if (strncmp(macros[j].name, &template->data[i + 1], strlen(macros[j].name)) == 0) {
805
 
                                        break;
806
 
                                }
807
 
                        }
808
 
                        if (j == (sizeof(macros) / sizeof(struct macro_def))) {
809
 
                                i++;
810
 
                                while ((template->data[i] >= 'A' && 
811
 
                                        template->data[i] <= 'Z') ||
812
 
                                       template->data[i] == '_') 
813
 
                                        i++;
814
 
                        }
815
 
                        else {
816
 
                                i += strlen(macros[j].name) + 1;
817
 
                                expand_macro(cfg, macros[j].id, template_escape, &format_ptr, &left, msg);
818
 
                        }
819
 
                }
820
 
                else {
821
 
                        *format_ptr = template->data[i];
822
 
                        format_ptr++;
823
 
                        i++;
824
 
                }
825
 
        }
826
 
        *format_ptr = 0;
827
 
        return c_format_cstring("%z", format);
828
 
}
829
 
 
830
498
/* FIXME: a binary search would be nicer */
831
499
static struct affile_dest_writer *
832
500
affile_find_writer(struct affile_dest *self, 
838
506
 
839
507
        if (self->flags & AFFILE_NO_EXPAND) {
840
508
                if (!self->writers) {
841
 
                        self->writers = make_affile_dest_writer(self, self->template_fname);
 
509
                        self->writers = make_affile_dest_writer(self, ol_string_use(self->template_fname));
842
510
                        res = LOG_HANDLER_INIT(self->writers, self->cfg, NULL);
843
511
                        if (res & ST_QUIT)
844
512
                                return NULL;
884
552
                self->super.log_fifo_size = cfg->log_fifo_size;
885
553
        if (cfg->create_dirs)
886
554
                self->flags |= AFFILE_CREATE_DIRS;
887
 
        if (self->uid == -1)
 
555
        if (self->uid == -2)
888
556
                self->uid = cfg->uid;
889
 
        if (self->gid == -1)
 
557
        if (self->gid == -2)
890
558
                self->gid = cfg->gid;
891
 
        if (self->perm == -1)
 
559
        if (self->perm == -2)
892
560
                self->perm = cfg->perm;
893
561
        if (self->dir_uid == -1)
894
562
                self->dir_uid = cfg->dir_uid;
922
590
        self->super.super.init = do_init_affile_dest;
923
591
        self->super.super.handler = do_handle_affile_log;
924
592
        self->super.log_fifo_size = -1;
925
 
        self->uid = self->gid = -1;
926
 
        self->perm = -1;
 
593
        self->uid = self->gid = -2;
 
594
        self->perm = -2;
927
595
        self->dir_uid = self->dir_gid = -1;
928
596
        self->dir_perm = -1;
929
597
        self->remove_if_older = -1;