[systemd-devel] [PATCH] shared/log.c: log_struct_internal(): handle multiple lines

harald at redhat.com harald at redhat.com
Wed Jun 26 06:06:37 PDT 2013


From: Harald Hoyer <harald at redhat.com>

Handle "VAR=line1\nline2\nline3" and split into
"VAR"
length
"line1\nline2\nline3"
"\n"
---
 src/shared/log.c | 45 ++++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 40 insertions(+), 5 deletions(-)

diff --git a/src/shared/log.c b/src/shared/log.c
index 27317f7..2eb3d63 100644
--- a/src/shared/log.c
+++ b/src/shared/log.c
@@ -735,12 +735,13 @@ int log_struct_internal(
             journal_fd >= 0) {
 
                 char header[LINE_MAX];
-                struct iovec iovec[17] = {};
-                unsigned n = 0, i;
+                struct iovec iovec[48] = {};
+                unsigned n = 0, i = 0;
                 struct msghdr mh = {
                         .msg_iov = iovec,
                 };
                 static const char nl = '\n';
+                uint64_t l[48] = {};
 
                 /* If the journal is available do structured logging */
                 log_do_header(header, sizeof(header), level,
@@ -748,9 +749,10 @@ int log_struct_internal(
                 IOVEC_SET_STRING(iovec[n++], header);
 
                 va_start(ap, format);
-                while (format && n + 1 < ELEMENTSOF(iovec)) {
+                while (format && n + 5 < ELEMENTSOF(iovec)) {
                         char *buf;
                         va_list aq;
+                        char *c, *nlp;
 
                         /* We need to copy the va_list structure,
                          * since vasprintf() leaves it afterwards at
@@ -768,7 +770,37 @@ int log_struct_internal(
                          * the next format string */
                         VA_FORMAT_ADVANCE(format, ap);
 
-                        IOVEC_SET_STRING(iovec[n++], buf);
+                        IOVEC_SET_STRING(iovec[n], buf);
+
+                        c = memchr(iovec[n].iov_base, '=', iovec[n].iov_len);
+                        nlp = memchr(iovec[n].iov_base, nl, iovec[n].iov_len);
+                        if (nlp && _likely_(nlp > c)) {
+                                struct iovec iov;
+                                iov.iov_base = iovec[n].iov_base;
+                                iov.iov_len = iovec[n].iov_len;
+
+                                /* Already includes a newline? Bummer, then
+                                 * let's write the variable name, then a
+                                 * newline, then the size (64bit LE), followed
+                                 * by the data and a final newline */
+                                i = n;
+                                iovec[n].iov_len = c - (char*) iov.iov_base;
+                                n++;
+
+                                iovec[n].iov_base = (char*) &nl;
+                                iovec[n].iov_len = 1;
+                                n++;
+
+                                l[i] = htole64(iov.iov_len - (c - (char*) iov.iov_base) - 1);
+                                iovec[n].iov_base = &l[i++];
+                                iovec[n].iov_len = sizeof(uint64_t);
+                                n++;
+
+                                iovec[n].iov_base = c + 1;
+                                iovec[n].iov_len = iov.iov_len - (c - (char*) iov.iov_base) - 1;
+                        }
+
+                        n++;
 
                         iovec[n].iov_base = (char*) &nl;
                         iovec[n].iov_len = 1;
@@ -786,8 +818,11 @@ int log_struct_internal(
 
         finish:
                 va_end(ap);
-                for (i = 1; i < n; i += 2)
+                for (i = 1; i < n; i += 2) {
                         free(iovec[i].iov_base);
+                        if (l[i])
+                                i += 3;
+                }
 
         } else {
                 char buf[LINE_MAX];
-- 
1.8.3.1



More information about the systemd-devel mailing list