#include "list.h"
#include "sd-daemon.h"
#include "tcpwrap.h"
+#include "def.h"
-#define STREAMS_MAX 256
+#define STREAMS_MAX 4096
#define SERVER_FD_MAX 16
-#define TIMEOUT ((int) (10*MSEC_PER_SEC))
+#define TIMEOUT_MSEC ((int) (DEFAULT_EXIT_USEC/USEC_PER_MSEC))
typedef struct Stream Stream;
uid_t uid;
gid_t gid;
- bool prefix;
+ bool prefix:1;
+ bool tee_console:1;
char buffer[LINE_MAX];
size_t length;
priority = s->priority;
- if (s->prefix &&
- p[0] == '<' &&
- p[1] >= '0' && p[1] <= '7' &&
- p[2] == '>') {
-
- /* Detected priority prefix */
- priority = LOG_MAKEPRI(LOG_FAC(priority), (p[1] - '0'));
-
- p += 3;
- }
+ if (s->prefix)
+ parse_syslog_priority(&p, &priority);
if (*p == 0)
return 0;
+ /* Patch in LOG_USER facility if necessary */
+ if ((priority & LOG_FACMASK) == 0)
+ priority = LOG_USER | LOG_PRI(priority);
+
/*
* The format glibc uses to talk to the syslog daemon is:
*
* We extend the latter to include the process name and pid.
*/
- snprintf(header_priority, sizeof(header_priority), "<%i>",
- s->target == STREAM_SYSLOG ? priority : LOG_PRI(priority));
+ snprintf(header_priority, sizeof(header_priority), "<%i>", priority);
char_array_0(header_priority);
if (s->target == STREAM_SYSLOG) {
} else
assert_not_reached("Unknown log target");
+ if (s->tee_console) {
+ int console;
+
+ if ((console = open_terminal("/dev/console", O_WRONLY|O_NOCTTY|O_CLOEXEC)) >= 0) {
+ IOVEC_SET_STRING(iovec[0], s->process);
+ IOVEC_SET_STRING(iovec[1], header_pid);
+ IOVEC_SET_STRING(iovec[2], p);
+ IOVEC_SET_STRING(iovec[3], (char*) "\n");
+
+ writev(console, iovec, 4);
+ }
+
+ }
+
return 0;
}
switch (s->state) {
case STREAM_TARGET:
- if (streq(p, "syslog"))
+ if (streq(p, "syslog") || streq(p, "syslog+console"))
s->target = STREAM_SYSLOG;
- else if (streq(p, "kmsg")) {
+ else if (streq(p, "kmsg") || streq(p, "kmsg+console")) {
if (s->server->kmsg_fd >= 0 && s->uid == 0)
s->target = STREAM_KMSG;
log_warning("Failed to parse log target line.");
return -EBADMSG;
}
+
+ if (endswith(p, "+console"))
+ s->tee_console = true;
+
s->state = STREAM_PRIORITY;
return 0;
/* We use ev.data.ptr instead of ev.data.fd here,
* since on 64bit archs fd is 32bit while a pointer is
- * 64bit. To make sure we can easily distuingish fd
+ * 64bit. To make sure we can easily distinguish fd
* values and pointer values we want to make sure to
* write the full field unconditionally. */
if ((k = epoll_wait(server.epoll_fd,
&event, 1,
- server.n_streams <= 0 ? TIMEOUT : -1)) < 0) {
+ server.n_streams <= 0 ? TIMEOUT_MSEC : -1)) < 0) {
if (errno == EINTR)
continue;