Changeset View
Changeset View
Standalone View
Standalone View
usr.sbin/syslogd/syslogd.c
Show First 20 Lines • Show All 130 Lines • ▼ Show 20 Lines | |||||
#include <errno.h> | #include <errno.h> | ||||
#include <fcntl.h> | #include <fcntl.h> | ||||
#include <fnmatch.h> | #include <fnmatch.h> | ||||
#include <libutil.h> | #include <libutil.h> | ||||
#include <limits.h> | #include <limits.h> | ||||
#include <netdb.h> | #include <netdb.h> | ||||
#include <paths.h> | #include <paths.h> | ||||
#include <signal.h> | #include <signal.h> | ||||
#include <stdbool.h> | |||||
#include <stdio.h> | #include <stdio.h> | ||||
#include <stdlib.h> | #include <stdlib.h> | ||||
#include <string.h> | #include <string.h> | ||||
#include <sysexits.h> | #include <sysexits.h> | ||||
#include <unistd.h> | #include <unistd.h> | ||||
#include <utmpx.h> | #include <utmpx.h> | ||||
#include "pathnames.h" | #include "pathnames.h" | ||||
▲ Show 20 Lines • Show All 215 Lines • ▼ Show 20 Lines | |||||
static int UniquePriority; /* Only log specified priority? */ | static int UniquePriority; /* Only log specified priority? */ | ||||
static int LogFacPri; /* Put facility and priority in log message: */ | static int LogFacPri; /* Put facility and priority in log message: */ | ||||
/* 0=no, 1=numeric, 2=names */ | /* 0=no, 1=numeric, 2=names */ | ||||
static int KeepKernFac; /* Keep remotely logged kernel facility */ | static int KeepKernFac; /* Keep remotely logged kernel facility */ | ||||
static int needdofsync = 0; /* Are any file(s) waiting to be fsynced? */ | static int needdofsync = 0; /* Are any file(s) waiting to be fsynced? */ | ||||
static struct pidfh *pfh; | static struct pidfh *pfh; | ||||
static int sigpipe[2]; /* Pipe to catch a signal during select(). */ | static int sigpipe[2]; /* Pipe to catch a signal during select(). */ | ||||
static bool RFC3164OutputFormat = true; /* Use legacy format by default. */ | |||||
static volatile sig_atomic_t MarkSet, WantDie, WantInitialize, WantReapchild; | static volatile sig_atomic_t MarkSet, WantDie, WantInitialize, WantReapchild; | ||||
struct iovlist; | |||||
static int allowaddr(char *); | static int allowaddr(char *); | ||||
static int addfile(struct filed *); | static int addfile(struct filed *); | ||||
static int addpeer(struct peer *); | static int addpeer(struct peer *); | ||||
static int addsock(struct sockaddr *, socklen_t, struct socklist *); | static int addsock(struct sockaddr *, socklen_t, struct socklist *); | ||||
static struct filed *cfline(const char *, const char *, const char *); | static struct filed *cfline(const char *, const char *, const char *); | ||||
static const char *cvthname(struct sockaddr *); | static const char *cvthname(struct sockaddr *); | ||||
static void deadq_enter(pid_t, const char *); | static void deadq_enter(pid_t, const char *); | ||||
static int deadq_remove(struct deadq_entry *); | static int deadq_remove(struct deadq_entry *); | ||||
static int deadq_removebypid(pid_t); | static int deadq_removebypid(pid_t); | ||||
static int decode(const char *, const CODE *); | static int decode(const char *, const CODE *); | ||||
static void die(int) __dead2; | static void die(int) __dead2; | ||||
static void dodie(int); | static void dodie(int); | ||||
static void dofsync(void); | static void dofsync(void); | ||||
static void domark(int); | static void domark(int); | ||||
static void fprintlog_first(struct filed *, const char *, const char *, | static void fprintlog_first(struct filed *, const char *, const char *, | ||||
const char *, const char *, const char *, const char *, int); | const char *, const char *, const char *, const char *, int); | ||||
static void fprintlog_write(struct filed *, struct iovlist *, int); | |||||
static void fprintlog_successive(struct filed *, int); | static void fprintlog_successive(struct filed *, int); | ||||
static void init(int); | static void init(int); | ||||
static void logerror(const char *); | static void logerror(const char *); | ||||
static void logmsg(int, const struct logtime *, const char *, const char *, | static void logmsg(int, const struct logtime *, const char *, const char *, | ||||
const char *, const char *, const char *, const char *, int); | const char *, const char *, const char *, const char *, int); | ||||
static void log_deadchild(pid_t, int, const char *); | static void log_deadchild(pid_t, int, const char *); | ||||
static void markit(void); | static void markit(void); | ||||
static int socksetup(struct peer *); | static int socksetup(struct peer *); | ||||
▲ Show 20 Lines • Show All 96 Lines • ▼ Show 20 Lines | main(int argc, char *argv[]) | ||||
struct peer *pe; | struct peer *pe; | ||||
struct socklist *sl; | struct socklist *sl; | ||||
pid_t ppid = 1, spid; | pid_t ppid = 1, spid; | ||||
char *p; | char *p; | ||||
if (madvise(NULL, 0, MADV_PROTECT) != 0) | if (madvise(NULL, 0, MADV_PROTECT) != 0) | ||||
dprintf("madvise() failed: %s\n", strerror(errno)); | dprintf("madvise() failed: %s\n", strerror(errno)); | ||||
while ((ch = getopt(argc, argv, "468Aa:b:cCdf:FHkl:m:nNop:P:sS:Tuv")) | while ((ch = getopt(argc, argv, "468Aa:b:cCdf:FHkl:m:nNoO:p:P:sS:Tuv")) | ||||
!= -1) | != -1) | ||||
switch (ch) { | switch (ch) { | ||||
#ifdef INET | #ifdef INET | ||||
case '4': | case '4': | ||||
family = PF_INET; | family = PF_INET; | ||||
break; | break; | ||||
#endif | #endif | ||||
#ifdef INET6 | #ifdef INET6 | ||||
▲ Show 20 Lines • Show All 106 Lines • ▼ Show 20 Lines | case 'm': /* mark interval */ | ||||
break; | break; | ||||
case 'N': | case 'N': | ||||
NoBind = 1; | NoBind = 1; | ||||
SecureMode = 1; | SecureMode = 1; | ||||
break; | break; | ||||
case 'n': | case 'n': | ||||
resolve = 0; | resolve = 0; | ||||
break; | break; | ||||
case 'O': | |||||
if (strcmp(optarg, "bsd") == 0 || | |||||
strcmp(optarg, "rfc3164") == 0) | |||||
RFC3164OutputFormat = true; | |||||
else if (strcmp(optarg, "syslog") == 0 || | |||||
strcmp(optarg, "rfc5424") == 0) | |||||
RFC3164OutputFormat = false; | |||||
else | |||||
usage(); | |||||
break; | |||||
case 'o': | case 'o': | ||||
use_bootfile = 1; | use_bootfile = 1; | ||||
break; | break; | ||||
case 'P': /* path for alt. PID */ | case 'P': /* path for alt. PID */ | ||||
PidFile = optarg; | PidFile = optarg; | ||||
break; | break; | ||||
case 's': /* no network mode */ | case 's': /* no network mode */ | ||||
SecureMode++; | SecureMode++; | ||||
▲ Show 20 Lines • Show All 243 Lines • ▼ Show 20 Lines | if (sa == NULL) | ||||
return; | return; | ||||
#endif | #endif | ||||
} | } | ||||
static void | static void | ||||
usage(void) | usage(void) | ||||
{ | { | ||||
fprintf(stderr, "%s\n%s\n%s\n%s\n%s\n", | fprintf(stderr, | ||||
"usage: syslogd [-468ACcdFHknosTuv] [-a allowed_peer]", | "usage: syslogd [-468ACcdFHknosTuv] [-a allowed_peer]\n" | ||||
" [-b bind_address] [-f config_file]", | " [-b bind_address] [-f config_file]\n" | ||||
" [-l [mode:]path] [-m mark_interval]", | " [-l [mode:]path] [-m mark_interval]\n" | ||||
" [-P pid_file] [-p log_socket]", | " [-O format] [-P pid_file] [-p log_socket]\n" | ||||
" [-S logpriv_socket]"); | " [-S logpriv_socket]\n"); | ||||
exit(1); | exit(1); | ||||
} | } | ||||
/* | /* | ||||
* Removes characters from log messages that are unsafe to display. | * Removes characters from log messages that are unsafe to display. | ||||
* TODO: Permit UTF-8 strings that include a BOM per RFC 5424? | * TODO: Permit UTF-8 strings that include a BOM per RFC 5424? | ||||
*/ | */ | ||||
static void | static void | ||||
▲ Show 20 Lines • Show All 656 Lines • ▼ Show 20 Lines | STAILQ_FOREACH(f, &fhead, next) { | ||||
if ((f->f_type == F_FILE) && | if ((f->f_type == F_FILE) && | ||||
(f->f_flags & FFLAG_NEEDSYNC)) { | (f->f_flags & FFLAG_NEEDSYNC)) { | ||||
f->f_flags &= ~FFLAG_NEEDSYNC; | f->f_flags &= ~FFLAG_NEEDSYNC; | ||||
(void)fsync(f->f_file); | (void)fsync(f->f_file); | ||||
} | } | ||||
} | } | ||||
} | } | ||||
#define IOV_SIZE 7 | /* | ||||
* List of iovecs to which entries can be appended. | |||||
* Used for constructing the message to be logged. | |||||
*/ | |||||
struct iovlist { | |||||
struct iovec iov[TTYMSG_IOV_MAX]; | |||||
size_t iovcnt; | |||||
size_t totalsize; | |||||
}; | |||||
static void | static void | ||||
fprintlog_first(struct filed *f, const char *hostname, const char *app_name, | iovlist_init(struct iovlist *il) | ||||
const char *procid, const char *msgid __unused, | |||||
const char *structured_data __unused, const char *msg, int flags) | |||||
{ | { | ||||
struct iovec iov[IOV_SIZE]; | |||||
struct addrinfo *r; | |||||
int l, lsent = 0; | |||||
char tagged_msg[MAXLINE + 1], line[MAXLINE + 1], greetings[200]; | |||||
char nul[] = "", space[] = " ", lf[] = "\n", crlf[] = "\r\n"; | |||||
char timebuf[RFC3164_DATELEN + 1]; | |||||
const char *msgret; | |||||
if (strftime(timebuf, sizeof(timebuf), RFC3164_DATEFMT, | il->iovcnt = 0; | ||||
&f->f_lasttime.tm) == 0) | il->totalsize = 0; | ||||
timebuf[0] = '\0'; | |||||
if (f->f_type == F_WALL) { | |||||
/* The time displayed is not synchornized with the other log | |||||
* destinations (like messages). Following fragment was using | |||||
* ctime(&now), which was updating the time every 30 sec. | |||||
* With f_lasttime, time is synchronized correctly. | |||||
*/ | |||||
iov[0] = (struct iovec){ | |||||
.iov_base = greetings, | |||||
.iov_len = snprintf(greetings, sizeof(greetings), | |||||
"\r\n\7Message from syslogd@%s " | |||||
"at %.24s ...\r\n", hostname, timebuf) | |||||
}; | |||||
if (iov[0].iov_len >= sizeof(greetings)) | |||||
iov[0].iov_len = sizeof(greetings) - 1; | |||||
iov[1] = (struct iovec){ | |||||
.iov_base = nul, | |||||
.iov_len = 0 | |||||
}; | |||||
} else { | |||||
iov[0] = (struct iovec){ | |||||
.iov_base = timebuf, | |||||
.iov_len = strlen(timebuf) | |||||
}; | |||||
iov[1] = (struct iovec){ | |||||
.iov_base = space, | |||||
.iov_len = 1 | |||||
}; | |||||
} | } | ||||
if (LogFacPri) { | static void | ||||
static char fp_buf[30]; /* Hollow laugh */ | iovlist_append(struct iovlist *il, const char *str) | ||||
int fac = f->f_prevpri & LOG_FACMASK; | { | ||||
int pri = LOG_PRI(f->f_prevpri); | size_t size; | ||||
const char *f_s = NULL; | |||||
char f_n[5]; /* Hollow laugh */ | |||||
const char *p_s = NULL; | |||||
char p_n[5]; /* Hollow laugh */ | |||||
if (LogFacPri > 1) { | /* Discard components if we've run out of iovecs. */ | ||||
const CODE *c; | if (il->iovcnt < nitems(il->iov)) { | ||||
size = strlen(str); | |||||
for (c = facilitynames; c->c_name; c++) { | il->iov[il->iovcnt++] = (struct iovec){ | ||||
if (c->c_val == fac) { | .iov_base = __DECONST(char *, str), | ||||
f_s = c->c_name; | .iov_len = size, | ||||
break; | }; | ||||
il->totalsize += size; | |||||
} | } | ||||
} | } | ||||
for (c = prioritynames; c->c_name; c++) { | |||||
if (c->c_val == pri) { | static void | ||||
p_s = c->c_name; | iovlist_truncate(struct iovlist *il, size_t size) | ||||
break; | { | ||||
} | struct iovec *last; | ||||
} | size_t diff; | ||||
} | |||||
if (!f_s) { | while (size > il->totalsize) { | ||||
snprintf(f_n, sizeof f_n, "%d", LOG_FAC(fac)); | diff = size - il->totalsize; | ||||
f_s = f_n; | last = &il->iov[il->iovcnt - 1]; | ||||
} | if (diff >= last->iov_len) { | ||||
if (!p_s) { | /* Remove the last iovec entirely. */ | ||||
snprintf(p_n, sizeof p_n, "%d", pri); | --il->iovcnt; | ||||
p_s = p_n; | il->totalsize -= last->iov_len; | ||||
} | |||||
snprintf(fp_buf, sizeof fp_buf, "<%s.%s> ", f_s, p_s); | |||||
iov[2] = (struct iovec){ | |||||
.iov_base = fp_buf, | |||||
.iov_len = strlen(fp_buf) | |||||
}; | |||||
} else { | } else { | ||||
iov[2] = (struct iovec){ | /* Remove the last iovec partially. */ | ||||
.iov_base = nul, | last->iov_len -= diff; | ||||
.iov_len = 0 | il->totalsize -= diff; | ||||
}; | |||||
} | } | ||||
/* Prepend the application name to the message if provided. */ | |||||
if (app_name != NULL) { | |||||
if (procid != NULL) | |||||
snprintf(tagged_msg, sizeof(tagged_msg), | |||||
"%s[%s]: %s", app_name, procid, msg); | |||||
else | |||||
snprintf(tagged_msg, sizeof(tagged_msg), | |||||
"%s: %s", app_name, msg); | |||||
msg = tagged_msg; | |||||
} | } | ||||
iov[3] = (struct iovec){ | } | ||||
.iov_base = __DECONST(char *, hostname), | |||||
.iov_len = strlen(hostname) | |||||
}; | |||||
iov[4] = (struct iovec){ | |||||
.iov_base = space, | |||||
.iov_len = 1 | |||||
}; | |||||
iov[5] = (struct iovec){ | |||||
.iov_base = __DECONST(char *, msg), | |||||
.iov_len = strlen(msg) | |||||
}; | |||||
dprintf("Logging to %s", TypeNames[f->f_type]); | |||||
f->f_time = now; | |||||
switch (f->f_type) { | static void | ||||
case F_UNUSED: | fprintlog_write(struct filed *f, struct iovlist *il, int flags) | ||||
dprintf("\n"); | { | ||||
kib: Are you sure that such assert is the good way to handle the situation ? You truncate the… | |||||
Not Done Inline ActionsThat's a good point. I've changed the code to tolerate running out of iovecs. Indeed; this is sort of a poor man's uio. It looks like we have nothing like that in userspace yet. :-/ ed: That's a good point. I've changed the code to tolerate running out of iovecs.
Indeed; this is… | |||||
break; | struct msghdr msghdr; | ||||
struct addrinfo *r; | |||||
struct socklist *sl; | |||||
const char *msgret; | |||||
ssize_t lsent; | |||||
switch (f->f_type) { | |||||
case F_FORW: | case F_FORW: | ||||
/* Truncate messages to RFC 5426 recommended size. */ | |||||
dprintf(" %s", f->fu_forw_hname); | dprintf(" %s", f->fu_forw_hname); | ||||
switch (f->fu_forw_addr->ai_addr->sa_family) { | switch (f->fu_forw_addr->ai_addr->sa_family) { | ||||
#ifdef INET | #ifdef INET | ||||
case AF_INET: | case AF_INET: | ||||
dprintf(":%d\n", | dprintf(":%d\n", | ||||
ntohs(satosin(f->fu_forw_addr->ai_addr)->sin_port)); | ntohs(satosin(f->fu_forw_addr->ai_addr)->sin_port)); | ||||
iovlist_truncate(il, 480); | |||||
break; | break; | ||||
#endif | #endif | ||||
#ifdef INET6 | #ifdef INET6 | ||||
case AF_INET6: | case AF_INET6: | ||||
dprintf(":%d\n", | dprintf(":%d\n", | ||||
ntohs(satosin6(f->fu_forw_addr->ai_addr)->sin6_port)); | ntohs(satosin6(f->fu_forw_addr->ai_addr)->sin6_port)); | ||||
iovlist_truncate(il, 1180); | |||||
break; | break; | ||||
#endif | #endif | ||||
default: | default: | ||||
dprintf("\n"); | dprintf("\n"); | ||||
} | } | ||||
/* check for local vs remote messages */ | |||||
if (strcasecmp(hostname, LocalHostName)) | |||||
l = snprintf(line, sizeof line - 1, | |||||
"<%d>%.15s Forwarded from %s: %s", | |||||
f->f_prevpri, (char *)iov[0].iov_base, | |||||
hostname, (char *)iov[5].iov_base); | |||||
else | |||||
l = snprintf(line, sizeof line - 1, "<%d>%.15s %s", | |||||
f->f_prevpri, (char *)iov[0].iov_base, | |||||
(char *)iov[5].iov_base); | |||||
if (l < 0) | |||||
l = 0; | |||||
else if (l > MAXLINE) | |||||
l = MAXLINE; | |||||
lsent = 0; | |||||
for (r = f->fu_forw_addr; r; r = r->ai_next) { | for (r = f->fu_forw_addr; r; r = r->ai_next) { | ||||
struct socklist *sl; | memset(&msghdr, 0, sizeof(msghdr)); | ||||
msghdr.msg_name = r->ai_addr; | |||||
msghdr.msg_namelen = r->ai_addrlen; | |||||
msghdr.msg_iov = il->iov; | |||||
msghdr.msg_iovlen = il->iovcnt; | |||||
STAILQ_FOREACH(sl, &shead, next) { | STAILQ_FOREACH(sl, &shead, next) { | ||||
if (sl->sl_ss.ss_family == AF_LOCAL || | if (sl->sl_ss.ss_family == AF_LOCAL || | ||||
sl->sl_ss.ss_family == AF_UNSPEC || | sl->sl_ss.ss_family == AF_UNSPEC || | ||||
sl->sl_socket < 0) | sl->sl_socket < 0) | ||||
continue; | continue; | ||||
lsent = sendto(sl->sl_socket, line, l, 0, | lsent = sendmsg(sl->sl_socket, &msghdr, 0); | ||||
r->ai_addr, r->ai_addrlen); | if (lsent == (ssize_t)il->totalsize) | ||||
if (lsent == l) | |||||
break; | break; | ||||
} | } | ||||
if (lsent == l && !send_to_all) | if (lsent == (ssize_t)il->totalsize && !send_to_all) | ||||
break; | break; | ||||
} | } | ||||
dprintf("lsent/l: %d/%d\n", lsent, l); | dprintf("lsent/totalsize: %zd/%zu\n", lsent, il->totalsize); | ||||
if (lsent != l) { | if (lsent != (ssize_t)il->totalsize) { | ||||
int e = errno; | int e = errno; | ||||
logerror("sendto"); | logerror("sendto"); | ||||
errno = e; | errno = e; | ||||
switch (errno) { | switch (errno) { | ||||
case ENOBUFS: | case ENOBUFS: | ||||
case ENETDOWN: | case ENETDOWN: | ||||
case ENETUNREACH: | case ENETUNREACH: | ||||
case EHOSTUNREACH: | case EHOSTUNREACH: | ||||
Show All 13 Lines | if (lsent != (ssize_t)il->totalsize) { | ||||
f->f_type = F_UNUSED; | f->f_type = F_UNUSED; | ||||
break; | break; | ||||
} | } | ||||
} | } | ||||
break; | break; | ||||
case F_FILE: | case F_FILE: | ||||
dprintf(" %s\n", f->fu_fname); | dprintf(" %s\n", f->fu_fname); | ||||
iov[6] = (struct iovec){ | iovlist_append(il, "\n"); | ||||
.iov_base = lf, | if (writev(f->f_file, il->iov, il->iovcnt) < 0) { | ||||
.iov_len = 1 | |||||
}; | |||||
if (writev(f->f_file, iov, nitems(iov)) < 0) { | |||||
/* | /* | ||||
* If writev(2) fails for potentially transient errors | * If writev(2) fails for potentially transient errors | ||||
* like the filesystem being full, ignore it. | * like the filesystem being full, ignore it. | ||||
* Otherwise remove this logfile from the list. | * Otherwise remove this logfile from the list. | ||||
*/ | */ | ||||
if (errno != ENOSPC) { | if (errno != ENOSPC) { | ||||
int e = errno; | int e = errno; | ||||
close_filed(f); | close_filed(f); | ||||
errno = e; | errno = e; | ||||
logerror(f->fu_fname); | logerror(f->fu_fname); | ||||
} | } | ||||
} else if ((flags & SYNC_FILE) && (f->f_flags & FFLAG_SYNC)) { | } else if ((flags & SYNC_FILE) && (f->f_flags & FFLAG_SYNC)) { | ||||
f->f_flags |= FFLAG_NEEDSYNC; | f->f_flags |= FFLAG_NEEDSYNC; | ||||
needdofsync = 1; | needdofsync = 1; | ||||
} | } | ||||
break; | break; | ||||
case F_PIPE: | case F_PIPE: | ||||
dprintf(" %s\n", f->fu_pipe_pname); | dprintf(" %s\n", f->fu_pipe_pname); | ||||
iov[6] = (struct iovec){ | iovlist_append(il, "\n"); | ||||
.iov_base = lf, | |||||
.iov_len = 1 | |||||
}; | |||||
if (f->fu_pipe_pid == 0) { | if (f->fu_pipe_pid == 0) { | ||||
if ((f->f_file = p_open(f->fu_pipe_pname, | if ((f->f_file = p_open(f->fu_pipe_pname, | ||||
&f->fu_pipe_pid)) < 0) { | &f->fu_pipe_pid)) < 0) { | ||||
logerror(f->fu_pipe_pname); | logerror(f->fu_pipe_pname); | ||||
break; | break; | ||||
} | } | ||||
} | } | ||||
if (writev(f->f_file, iov, nitems(iov)) < 0) { | if (writev(f->f_file, il->iov, il->iovcnt) < 0) { | ||||
int e = errno; | int e = errno; | ||||
deadq_enter(f->fu_pipe_pid, f->fu_pipe_pname); | deadq_enter(f->fu_pipe_pid, f->fu_pipe_pname); | ||||
close_filed(f); | close_filed(f); | ||||
errno = e; | errno = e; | ||||
logerror(f->fu_pipe_pname); | logerror(f->fu_pipe_pname); | ||||
} | } | ||||
break; | break; | ||||
case F_CONSOLE: | case F_CONSOLE: | ||||
if (flags & IGN_CONS) { | if (flags & IGN_CONS) { | ||||
dprintf(" (ignored)\n"); | dprintf(" (ignored)\n"); | ||||
break; | break; | ||||
} | } | ||||
/* FALLTHROUGH */ | /* FALLTHROUGH */ | ||||
case F_TTY: | case F_TTY: | ||||
dprintf(" %s%s\n", _PATH_DEV, f->fu_fname); | dprintf(" %s%s\n", _PATH_DEV, f->fu_fname); | ||||
iov[6] = (struct iovec){ | iovlist_append(il, "\r\n"); | ||||
.iov_base = crlf, | |||||
.iov_len = 2 | |||||
}; | |||||
errno = 0; /* ttymsg() only sometimes returns an errno */ | errno = 0; /* ttymsg() only sometimes returns an errno */ | ||||
if ((msgret = ttymsg(iov, nitems(iov), f->fu_fname, 10))) { | if ((msgret = ttymsg(il->iov, il->iovcnt, f->fu_fname, 10))) { | ||||
f->f_type = F_UNUSED; | f->f_type = F_UNUSED; | ||||
logerror(msgret); | logerror(msgret); | ||||
} | } | ||||
break; | break; | ||||
case F_USERS: | case F_USERS: | ||||
case F_WALL: | case F_WALL: | ||||
dprintf("\n"); | dprintf("\n"); | ||||
iov[6] = (struct iovec){ | iovlist_append(il, "\r\n"); | ||||
.iov_base = crlf, | wallmsg(f, il->iov, il->iovcnt); | ||||
.iov_len = 2 | |||||
}; | |||||
wallmsg(f, iov, nitems(iov)); | |||||
break; | break; | ||||
} | } | ||||
} | |||||
static void | |||||
fprintlog_rfc5424(struct filed *f, const char *hostname, const char *app_name, | |||||
const char *procid, const char *msgid, const char *structured_data, | |||||
const char *msg, int flags) | |||||
{ | |||||
struct iovlist il; | |||||
suseconds_t usec; | |||||
int i; | |||||
char timebuf[33], priority_number[5]; | |||||
iovlist_init(&il); | |||||
if (f->f_type == F_WALL) | |||||
iovlist_append(&il, "\r\n\aMessage from syslogd ...\r\n"); | |||||
iovlist_append(&il, "<"); | |||||
snprintf(priority_number, sizeof(priority_number), "%d", f->f_prevpri); | |||||
iovlist_append(&il, priority_number); | |||||
iovlist_append(&il, ">1 "); | |||||
if (strftime(timebuf, sizeof(timebuf), "%FT%T.______%z", | |||||
&f->f_lasttime.tm) == sizeof(timebuf) - 2) { | |||||
/* Add colon to the time zone offset, which %z doesn't do. */ | |||||
timebuf[32] = '\0'; | |||||
timebuf[31] = timebuf[30]; | |||||
timebuf[30] = timebuf[29]; | |||||
timebuf[29] = ':'; | |||||
/* Overwrite space for microseconds with actual value. */ | |||||
usec = f->f_lasttime.usec; | |||||
for (i = 25; i >= 20; --i) { | |||||
timebuf[i] = usec % 10 + '0'; | |||||
usec /= 10; | |||||
} | |||||
iovlist_append(&il, timebuf); | |||||
} else | |||||
iovlist_append(&il, "-"); | |||||
iovlist_append(&il, " "); | |||||
iovlist_append(&il, hostname); | |||||
iovlist_append(&il, " "); | |||||
iovlist_append(&il, app_name == NULL ? "-" : app_name); | |||||
iovlist_append(&il, " "); | |||||
iovlist_append(&il, procid == NULL ? "-" : procid); | |||||
iovlist_append(&il, " "); | |||||
iovlist_append(&il, msgid == NULL ? "-" : msgid); | |||||
iovlist_append(&il, " "); | |||||
iovlist_append(&il, structured_data == NULL ? "-" : structured_data); | |||||
iovlist_append(&il, " "); | |||||
iovlist_append(&il, msg); | |||||
fprintlog_write(f, &il, flags); | |||||
} | |||||
static void | |||||
fprintlog_rfc3164(struct filed *f, const char *hostname, const char *app_name, | |||||
Not Done Inline ActionsPlease use fprintlog_rfc3164 instead of fprintlog_bsd to be consistent with the input parsing code. woodsb02: Please use fprintlog_rfc3164 instead of fprintlog_bsd to be consistent with the input parsing… | |||||
Not Done Inline ActionsDone! ed: Done! | |||||
const char *procid, const char *msg, int flags) | |||||
{ | |||||
struct iovlist il; | |||||
const CODE *c; | |||||
int facility, priority; | |||||
char timebuf[RFC3164_DATELEN + 1], facility_number[5], | |||||
priority_number[5]; | |||||
bool facility_found, priority_found; | |||||
if (strftime(timebuf, sizeof(timebuf), RFC3164_DATEFMT, | |||||
&f->f_lasttime.tm) == 0) | |||||
timebuf[0] = '\0'; | |||||
iovlist_init(&il); | |||||
switch (f->f_type) { | |||||
case F_FORW: | |||||
/* Message forwarded over the network. */ | |||||
iovlist_append(&il, "<"); | |||||
snprintf(priority_number, sizeof(priority_number), "%d", | |||||
f->f_prevpri); | |||||
iovlist_append(&il, priority_number); | |||||
iovlist_append(&il, ">"); | |||||
iovlist_append(&il, timebuf); | |||||
if (strcasecmp(hostname, LocalHostName) != 0) { | |||||
iovlist_append(&il, " Forwarded from "); | |||||
iovlist_append(&il, hostname); | |||||
iovlist_append(&il, ":"); | |||||
} | |||||
iovlist_append(&il, " "); | |||||
break; | |||||
case F_WALL: | |||||
/* Message written to terminals. */ | |||||
iovlist_append(&il, "\r\n\aMessage from syslogd@"); | |||||
iovlist_append(&il, hostname); | |||||
iovlist_append(&il, " at "); | |||||
iovlist_append(&il, timebuf); | |||||
iovlist_append(&il, " ...\r\n"); | |||||
break; | |||||
default: | |||||
/* Message written to files. */ | |||||
iovlist_append(&il, timebuf); | |||||
iovlist_append(&il, " "); | |||||
iovlist_append(&il, hostname); | |||||
iovlist_append(&il, " "); | |||||
if (LogFacPri) { | |||||
iovlist_append(&il, "<"); | |||||
facility = f->f_prevpri & LOG_FACMASK; | |||||
facility_found = false; | |||||
if (LogFacPri > 1) { | |||||
for (c = facilitynames; c->c_name; c++) { | |||||
if (c->c_val == facility) { | |||||
iovlist_append(&il, c->c_name); | |||||
facility_found = true; | |||||
break; | |||||
} | |||||
} | |||||
} | |||||
if (!facility_found) { | |||||
snprintf(facility_number, | |||||
sizeof(facility_number), "%d", | |||||
LOG_FAC(facility)); | |||||
iovlist_append(&il, facility_number); | |||||
} | |||||
iovlist_append(&il, "."); | |||||
priority = LOG_PRI(f->f_prevpri); | |||||
priority_found = false; | |||||
if (LogFacPri > 1) { | |||||
for (c = prioritynames; c->c_name; c++) { | |||||
if (c->c_val == priority) { | |||||
iovlist_append(&il, c->c_name); | |||||
priority_found = true; | |||||
break; | |||||
} | |||||
} | |||||
} | |||||
if (!priority_found) { | |||||
snprintf(priority_number, | |||||
sizeof(priority_number), "%d", priority); | |||||
iovlist_append(&il, priority_number); | |||||
} | |||||
iovlist_append(&il, "> "); | |||||
} | |||||
break; | |||||
} | |||||
/* Message body with application name and process ID prefixed. */ | |||||
if (app_name != NULL) { | |||||
iovlist_append(&il, app_name); | |||||
if (procid != NULL) { | |||||
iovlist_append(&il, "["); | |||||
iovlist_append(&il, procid); | |||||
iovlist_append(&il, "]"); | |||||
} | |||||
iovlist_append(&il, ": "); | |||||
} | |||||
iovlist_append(&il, msg); | |||||
fprintlog_write(f, &il, flags); | |||||
} | |||||
static void | |||||
fprintlog_first(struct filed *f, const char *hostname, const char *app_name, | |||||
const char *procid, const char *msgid __unused, | |||||
const char *structured_data __unused, const char *msg, int flags) | |||||
{ | |||||
dprintf("Logging to %s", TypeNames[f->f_type]); | |||||
f->f_time = now; | |||||
f->f_prevcount = 0; | f->f_prevcount = 0; | ||||
if (f->f_type == F_UNUSED) { | |||||
dprintf("\n"); | |||||
return; | |||||
} | } | ||||
if (RFC3164OutputFormat) | |||||
fprintlog_rfc3164(f, hostname, app_name, procid, msg, flags); | |||||
else | |||||
fprintlog_rfc5424(f, hostname, app_name, procid, msgid, | |||||
structured_data, msg, flags); | |||||
} | |||||
/* | /* | ||||
* Prints a message to a log file that the previously logged message was | * Prints a message to a log file that the previously logged message was | ||||
* received multiple times. | * received multiple times. | ||||
*/ | */ | ||||
static void | static void | ||||
fprintlog_successive(struct filed *f, int flags) | fprintlog_successive(struct filed *f, int flags) | ||||
{ | { | ||||
char msg[100]; | char msg[100]; | ||||
▲ Show 20 Lines • Show All 377 Lines • ▼ Show 20 Lines | init(int signo) | ||||
* Load hostname (may have changed). | * Load hostname (may have changed). | ||||
*/ | */ | ||||
if (signo != 0) | if (signo != 0) | ||||
(void)strlcpy(oldLocalHostName, LocalHostName, | (void)strlcpy(oldLocalHostName, LocalHostName, | ||||
sizeof(oldLocalHostName)); | sizeof(oldLocalHostName)); | ||||
if (gethostname(LocalHostName, sizeof(LocalHostName))) | if (gethostname(LocalHostName, sizeof(LocalHostName))) | ||||
err(EX_OSERR, "gethostname() failed"); | err(EX_OSERR, "gethostname() failed"); | ||||
if ((p = strchr(LocalHostName, '.')) != NULL) { | if ((p = strchr(LocalHostName, '.')) != NULL) { | ||||
*p++ = '\0'; | /* RFC 5424 prefers logging FQDNs. */ | ||||
LocalDomain = p; | if (RFC3164OutputFormat) | ||||
*p = '\0'; | |||||
LocalDomain = p + 1; | |||||
} else { | } else { | ||||
LocalDomain = ""; | LocalDomain = ""; | ||||
} | } | ||||
/* | /* | ||||
* Load / reload timezone data (in case it changed). | * Load / reload timezone data (in case it changed). | ||||
* | * | ||||
* Just calling tzset() again does not work, the timezone code | * Just calling tzset() again does not work, the timezone code | ||||
▲ Show 20 Lines • Show All 1,189 Lines • Show Last 20 Lines |
Are you sure that such assert is the good way to handle the situation ? You truncate the output anyway, at least for some formats. IMO it is somewhat frightening to know that such important service as syslogd could be shut down by some inaccuracy instead of tolerating it.
In other words, I believe that in case of programming error, most people would prefer to get even truncated message instead of losing all their logs.
If you make iov dynamically allocated, you re-invent struct uio.