Hi, When writing my regression test for syslogd, I realized that with LOG_CONS and LOG_PERROR trailing new lines are printed. Of course Perl Sys::Syslog that I use for the tests has bugs and appends '\n' in cases where it should not.
But then I found this sentence in our man 3 syslog: A trailing newline is added if none is present. There is no such check in our syslog_r(3) libc function. It unconditionally adds new lines when writing to stderr or console. I would recommend to remove any trailing new line before adding it. The syslog rfc does not want trailing new lines, our syslogd converts them to spaces, and contrary to the documentation syslog_r(3) prints empty lines. While there, I found that LOG_CONS uses strchr() to find the beginning of the string. The code for LOG_PERROR saves a pointer. I would like to make a consistent implementation with conp and stdp pointer. Also add a check that iov_len does not get negative, even if we remove a new line. And fix the compiler warning /usr/src/lib/libc/gen/syslog_r.c:93: warning: 'stdp' may be used uninitialized in this function ok? bluhm Index: lib/libc/gen/syslog_r.c =================================================================== RCS file: /data/mirror/openbsd/cvs/src/lib/libc/gen/syslog_r.c,v retrieving revision 1.5 diff -u -p -r1.5 syslog_r.c --- lib/libc/gen/syslog_r.c 14 Jul 2014 03:52:04 -0000 1.5 +++ lib/libc/gen/syslog_r.c 29 Aug 2014 20:33:00 -0000 @@ -90,7 +90,7 @@ __vsyslog_r(int pri, struct syslog_data int fd, saved_errno, error; #define TBUF_LEN 2048 #define FMT_LEN 1024 - char *stdp, tbuf[TBUF_LEN], fmt_cpy[FMT_LEN]; + char *conp = NULL, *stdp = NULL, tbuf[TBUF_LEN], fmt_cpy[FMT_LEN]; int tbuf_left, fmt_left, prlen; #define INTERNALLOG LOG_ERR|LOG_CONS|LOG_PERROR|LOG_PID @@ -127,6 +127,8 @@ __vsyslog_r(int pri, struct syslog_data prlen = snprintf(p, tbuf_left, "<%d>", pri); DEC(); + if (data->log_stat & LOG_CONS) + conp = p; /* * syslogd will expand time automagically for reentrant case, and @@ -195,13 +197,17 @@ __vsyslog_r(int pri, struct syslog_data prlen = vsnprintf(p, tbuf_left, fmt_cpy, ap); DEC(); cnt = p - tbuf; + if (cnt > 0 && p[-1] == '\n') { + *(--p) = '\0'; + --cnt; + } /* Output to stderr if requested. */ if (data->log_stat & LOG_PERROR) { struct iovec iov[2]; iov[0].iov_base = stdp; - iov[0].iov_len = cnt - (stdp - tbuf); + iov[0].iov_len = cnt > stdp - tbuf ? cnt - (stdp - tbuf) : 0; iov[1].iov_base = "\n"; iov[1].iov_len = 1; (void)writev(STDERR_FILENO, iov, 2); @@ -222,9 +228,8 @@ __vsyslog_r(int pri, struct syslog_data (fd = open(_PATH_CONSOLE, O_WRONLY|O_NONBLOCK, 0)) >= 0) { struct iovec iov[2]; - p = strchr(tbuf, '>') + 1; - iov[0].iov_base = p; - iov[0].iov_len = cnt - (p - tbuf); + iov[0].iov_base = conp; + iov[0].iov_len = cnt > conp - tbuf ? cnt - (conp - tbuf) : 0; iov[1].iov_base = "\r\n"; iov[1].iov_len = 2; (void)writev(fd, iov, 2);