20
20
* Inspired by nsyslog, originally written by Darren Reed.
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 $
24
24
***************************************************************************/
27
* Several patches to the macro expansion function were contributed
30
* Portions Copyright (c) 2002 by Gert Menke
31
* All rights reserved.
33
* Redistribution and use in source and binary forms, with or without
34
* modification, are permitted provided that the following conditions
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.
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
26
58
#include "affile.h"
27
59
#include "format.h"
53
86
#include <netinet/in.h>
54
87
#include <arpa/inet.h>
57
expand_macros(struct syslog_config *cfg, struct ol_string *template, int template_escape, struct log_info *msg);
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)
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);
100
if (strncmp((char *) name->data, "/dev", 4) == 0) {
101
werror("Changing permissions on special file %S\n", name);
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;
76
109
p = strchr(p, '/');
80
if (stat(name->data, &st) == 0) {
113
if (stat((char *) name->data, &st) == 0) {
81
114
if (!S_ISDIR(st.st_mode))
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)
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);
93
126
p = strchr(p + 1, '/');
95
*fd = open(name->data, flags, mode);
128
*fd = open((char *) name->data, flags, mode);
97
130
if (uid != -1 || gid != -1)
98
chown(name->data, uid, gid);
131
chown((char *) name->data, uid, gid);
100
chmod(name->data, mode);
133
chmod((char *) name->data, mode);
101
134
return *fd != -1;
449
#define MAX_MACRO_ARGS 32
450
#define MAX_EXPANDED_MACRO 2048
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
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
494
#define M_FULLHOST 33
500
#define M_SOURCE_IP 37
502
int append_string(char **dest, int *left, char *str, int length, int escape)
507
l = MIN(length, *left - 1);
508
strncpy(*dest, str, l);
514
for (p = str; length && ((*left - l) > 1); p++, length--, l++) {
515
if (*p == '\'' || *p == '\"' || *p == '\\') {
519
*(*dest + l + 1) = *p;
530
void expand_macro(struct syslog_config *cfg, int id, int escape, char **dest, int *left, struct log_info *msg)
537
char *n = syslog_lookup_value(msg->pri & LOG_FACMASK, sl_facilities);
539
length = append_string(dest, left, n, strlen(n), 0);
542
length = snprintf(*dest, *left, "%x", (msg->pri & LOG_FACMASK) >> 3);
548
char *n = syslog_lookup_value(msg->pri & LOG_PRIMASK, sl_levels);
550
length = append_string(dest, left, n, strlen(n), 0);
553
/* should never happen */
554
length = snprintf(*dest, *left, "%d", msg->pri & LOG_PRIMASK);
560
length = snprintf(*dest, *left, "%02x", msg->pri);
565
length = append_string(dest, left, msg->host->data, msg->host->length, escape);
572
CAST(inet_address_info, addr, msg->saddr);
574
ip = inet_ntoa(addr->sa.sin_addr);
579
length = append_string(dest, left, ip, strlen(ip), escape);
584
UINT8 *p1 = memchr(msg->host->data, '@', msg->host->length);
591
p1 = msg->host->data;
592
remaining = msg->host->length - (p1 - msg->host->data);
593
p2 = memchr(p1, '/', remaining);
595
length = MIN(p2 - p1, *left);
598
length = MIN(*left, msg->host->length - (p1 - msg->host->data));
600
length = append_string(dest, left, p1, length, escape);
606
length = append_string(dest, left, msg->program->data, msg->program->length, escape);
610
case M_FULLDATE_RECVD:
611
case M_ISODATE_RECVD:
612
case M_WEEKDAY_RECVD:
621
case M_FULLDATE_STAMP:
622
case M_ISODATE_STAMP:
623
case M_WEEKDAY_STAMP:
642
/* year, month, day */
646
case M_FULLDATE_RECVD:
647
case M_ISODATE_RECVD:
648
case M_WEEKDAY_RECVD:
656
tm = localtime(&msg->recvd);
658
case M_FULLDATE_STAMP:
659
case M_ISODATE_STAMP:
660
case M_WEEKDAY_STAMP:
668
tm = localtime(&msg->stamp);
671
if (cfg->use_time_recvd)
672
tm = localtime(&msg->recvd);
674
tm = localtime(&msg->stamp);
680
case M_WEEKDAY_RECVD:
681
case M_WEEKDAY_STAMP:
682
length = strftime(*dest, *left - 1, "%a", tm);
687
length = snprintf(*dest, *left, "%04d", tm->tm_year + 1900);
692
length = snprintf(*dest, *left, "%02d", tm->tm_mon + 1);
697
length = snprintf(*dest, *left, "%02d", tm->tm_mday);
702
length = snprintf(*dest, *left, "%02d", tm->tm_hour);
707
length = snprintf(*dest, *left, "%02d", tm->tm_min);
712
length = snprintf(*dest, *left, "%02d", tm->tm_sec);
715
case M_ISODATE_RECVD:
716
case M_ISODATE_STAMP:
717
length = strftime(*dest, *left - 1, "%Y-%m-%dT%H:%M:%S%z", tm);
720
case M_FULLDATE_RECVD:
721
case M_FULLDATE_STAMP:
722
length = strftime(*dest, *left - 1, "%Y %h %e %H:%M:%S", tm);
727
length = strftime(*dest, *left - 1, "%h %e %H:%M:%S", tm);
734
length = append_string(dest, left, msg->msg->data, msg->msg->length, escape);
745
expand_macros(struct syslog_config *cfg, struct ol_string *template, int template_escape, struct log_info *msg)
747
static struct macro_def macros[] = {
748
{ "FACILITY", M_FACILITY },
749
{ "PRIORITY", M_LEVEL },
750
{ "LEVEL", M_LEVEL },
754
{ "FULLDATE", M_FULLDATE },
755
{ "ISODATE", M_ISODATE },
757
{ "MONTH", M_MONTH },
762
{ "WEEKDAY", M_WEEKDAY },
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 },
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 },
787
{ "FULLHOST", M_FULLHOST },
789
{ "PROGRAM", M_PROGRAM },
790
{ "MSG", M_MESSAGE },
791
{ "MESSAGE", M_MESSAGE },
792
{ "SOURCEIP", M_SOURCE_IP }
794
char format[MAX_EXPANDED_MACRO], *format_ptr = format;
795
int left = sizeof(format);
799
while (left && (i < template->length)) {
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) {
808
if (j == (sizeof(macros) / sizeof(struct macro_def))) {
810
while ((template->data[i] >= 'A' &&
811
template->data[i] <= 'Z') ||
812
template->data[i] == '_')
816
i += strlen(macros[j].name) + 1;
817
expand_macro(cfg, macros[j].id, template_escape, &format_ptr, &left, msg);
821
*format_ptr = template->data[i];
827
return c_format_cstring("%z", format);
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,