From ca8625e9f9f1e0ec11d9976436eb95ec8651f8d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Sat, 23 Jan 2016 19:41:45 -0500 Subject: [PATCH 1/4] TODO: remove syslog broadcasting This should most likely be implemented as part of journal-netlogd (https://github.com/systemd/systemd/pull/1890), which it seems is not going to be merged. systemctl edit was mentioned twice. --- TODO | 6 ------ 1 file changed, 6 deletions(-) diff --git a/TODO b/TODO index 99c2e547b8..f9e2d4761a 100644 --- a/TODO +++ b/TODO @@ -73,8 +73,6 @@ Features: * consider throwing a warning if a service declares it wants to be "Before=" a .device unit. -* "systemctl edit" should know a mode to create a new unit file - * there's probably something wrong with having user mounts below /sys, as we have for debugfs. for exmaple, src/core/mount.c handles mounts prefixed with /sys generally special. @@ -496,10 +494,6 @@ Features: - journal-or-kmsg is currently broken? See reverted commit 4a01181e460686d8b4a543b1dfa7f77c9e3c5ab8. - man: document that corrupted journal files is nothing to act on - - systemd-journal-upload (or a new, related tool): allow pushing out - journal messages onto the network in BSD syslog protocol, - continuously. Default to some link-local IP mcast group, to make this - useful as a one-stop debugging tool. - rework journald sigbus stuff to use mutex - Set RLIMIT_NPROC for systemd-journal-xyz, and all other of our services that run under their own user ids, and use User= (but only From 8a03c9ef744e13dc700a7e7ca6cae8afdcf0d71c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Sun, 8 Nov 2015 14:05:55 -0500 Subject: [PATCH 2/4] journald: allow additional payload in server_driver_message The code to format the iovec is shared with log.c. All call sites to server_driver_message are changed to include the additional "MESSAGE=" part, but the new functionality is not used and change in functionality is not expected. iovec is preallocated, so the maximum number of messages is limited. In server_driver_message N_IOVEC_PAYLOAD_FIELDS is currently set to 1. New code is not oom safe, it will fail if memory cannot be allocated. This will be fixed in subsequent commit. --- src/basic/log.c | 89 +++++++++++++++++++++-------------- src/basic/log.h | 10 ++++ src/journal/journald-kmsg.c | 6 ++- src/journal/journald-server.c | 36 +++++++++----- src/journal/journald-server.h | 3 +- src/journal/journald-syslog.c | 5 +- src/journal/journald.c | 8 +++- 7 files changed, 102 insertions(+), 55 deletions(-) diff --git a/src/basic/log.c b/src/basic/log.c index a2bc0d5be2..18d4b82be2 100644 --- a/src/basic/log.c +++ b/src/basic/log.c @@ -805,6 +805,52 @@ int log_oom_internal(const char *file, int line, const char *func) { return -ENOMEM; } +int log_format_iovec( + struct iovec *iovec, + unsigned iovec_len, + unsigned *n, + bool newline_separator, + int error, + const char *format, + va_list ap) { + + static const char nl = '\n'; + + while (format && *n + 1 < iovec_len) { + va_list aq; + char *m; + int r; + + /* We need to copy the va_list structure, + * since vasprintf() leaves it afterwards at + * an undefined location */ + + if (error != 0) + errno = error; + + va_copy(aq, ap); + r = vasprintf(&m, format, aq); + va_end(aq); + if (r < 0) + return -EINVAL; + + /* Now, jump enough ahead, so that we point to + * the next format string */ + VA_FORMAT_ADVANCE(format, ap); + + IOVEC_SET_STRING(iovec[(*n)++], m); + + if (newline_separator) { + iovec[*n].iov_base = (char*) &nl; + iovec[*n].iov_len = 1; + (*n)++; + } + + format = va_arg(ap, char *); + } + return 0; +} + int log_struct_internal( int level, int error, @@ -837,10 +883,10 @@ int log_struct_internal( char header[LINE_MAX]; struct iovec iovec[17] = {}; unsigned n = 0, i; + int r; struct msghdr mh = { .msg_iov = iovec, }; - static const char nl = '\n'; bool fallback = false; /* If the journal is available do structured logging */ @@ -848,43 +894,14 @@ int log_struct_internal( IOVEC_SET_STRING(iovec[n++], header); va_start(ap, format); - while (format && n + 1 < ELEMENTSOF(iovec)) { - va_list aq; - char *m; - - /* We need to copy the va_list structure, - * since vasprintf() leaves it afterwards at - * an undefined location */ - - if (error != 0) - errno = error; - - va_copy(aq, ap); - if (vasprintf(&m, format, aq) < 0) { - va_end(aq); - fallback = true; - goto finish; - } - va_end(aq); - - /* Now, jump enough ahead, so that we point to - * the next format string */ - VA_FORMAT_ADVANCE(format, ap); - - IOVEC_SET_STRING(iovec[n++], m); - - iovec[n].iov_base = (char*) &nl; - iovec[n].iov_len = 1; - n++; - - format = va_arg(ap, char *); + r = log_format_iovec(iovec, ELEMENTSOF(iovec), &n, true, error, format, ap); + if (r < 0) + fallback = true; + else { + mh.msg_iovlen = n; + (void) sendmsg(journal_fd, &mh, MSG_NOSIGNAL); } - mh.msg_iovlen = n; - - (void) sendmsg(journal_fd, &mh, MSG_NOSIGNAL); - - finish: va_end(ap); for (i = 1; i < n; i += 2) free(iovec[i].iov_base); diff --git a/src/basic/log.h b/src/basic/log.h index cda1e45cc8..8c7c5e4598 100644 --- a/src/basic/log.h +++ b/src/basic/log.h @@ -26,6 +26,7 @@ #include #include #include +#include #include #include "sd-id128.h" @@ -127,6 +128,15 @@ int log_oom_internal( int line, const char *func); +int log_format_iovec( + struct iovec *iovec, + unsigned iovec_len, + unsigned *n, + bool newline_separator, + int error, + const char *format, + va_list ap); + /* This modifies the buffer passed! */ int log_dump_internal( int level, diff --git a/src/journal/journald-kmsg.c b/src/journal/journald-kmsg.c index e048e04716..1306ad6974 100644 --- a/src/journal/journald-kmsg.c +++ b/src/journal/journald-kmsg.c @@ -158,8 +158,10 @@ static void dev_kmsg_record(Server *s, const char *p, size_t l) { /* Did we lose any? */ if (serial > *s->kernel_seqnum) - server_driver_message(s, SD_MESSAGE_JOURNAL_MISSED, "Missed %"PRIu64" kernel messages", - serial - *s->kernel_seqnum); + server_driver_message(s, SD_MESSAGE_JOURNAL_MISSED, + LOG_MESSAGE("Missed %"PRIu64" kernel messages", + serial - *s->kernel_seqnum), + NULL); /* Make sure we never read this one again. Note that * we always store the next message serial we expect diff --git a/src/journal/journald-server.c b/src/journal/journald-server.c index cfcc2c4302..6df71953e8 100644 --- a/src/journal/journald-server.c +++ b/src/journal/journald-server.c @@ -70,6 +70,7 @@ #include "string-table.h" #include "string-util.h" #include "user-util.h" +#include "log.h" #define USER_JOURNALS_MAX 1024 @@ -142,7 +143,7 @@ static int determine_space_for( sum += (uint64_t) st.st_blocks * 512UL; } - /* If request, then let's bump the min_use limit to the + /* If requested, then let's bump the min_use limit to the * current usage on disk. We do this when starting up and * first opening the journal files. This way sudden spikes in * disk usage will not cause journald to vacuum files without @@ -164,6 +165,7 @@ static int determine_space_for( fb4[FORMAT_BYTES_MAX], fb5[FORMAT_BYTES_MAX], fb6[FORMAT_BYTES_MAX]; server_driver_message(s, SD_MESSAGE_JOURNAL_USAGE, + LOG_MESSAGE( "%s (%s) is currently using %s.\n" "Maximum allowed usage is set to %s.\n" "Leaving at least %s free (of currently available %s of space).\n" @@ -174,7 +176,8 @@ static int determine_space_for( format_bytes(fb3, sizeof(fb3), metrics->keep_free), format_bytes(fb4, sizeof(fb4), ss_avail), format_bytes(fb5, sizeof(fb5), s->cached_space_limit), - format_bytes(fb6, sizeof(fb6), s->cached_space_available)); + format_bytes(fb6, sizeof(fb6), s->cached_space_available)), + NULL); } if (available) @@ -808,9 +811,8 @@ static void dispatch_message_real( void server_driver_message(Server *s, sd_id128_t message_id, const char *format, ...) { char mid[11 + 32 + 1]; - char buffer[16 + LINE_MAX + 1]; - struct iovec iovec[N_IOVEC_META_FIELDS + 6]; - int n = 0; + struct iovec iovec[N_IOVEC_META_FIELDS + 5 + N_IOVEC_PAYLOAD_FIELDS]; + unsigned n = 0, m; va_list ap; struct ucred ucred = {}; @@ -823,22 +825,25 @@ void server_driver_message(Server *s, sd_id128_t message_id, const char *format, IOVEC_SET_STRING(iovec[n++], "PRIORITY=6"); IOVEC_SET_STRING(iovec[n++], "_TRANSPORT=driver"); - memcpy(buffer, "MESSAGE=", 8); - va_start(ap, format); - vsnprintf(buffer + 8, sizeof(buffer) - 8, format, ap); - va_end(ap); - IOVEC_SET_STRING(iovec[n++], buffer); - if (!sd_id128_equal(message_id, SD_ID128_NULL)) { snprintf(mid, sizeof(mid), LOG_MESSAGE_ID(message_id)); IOVEC_SET_STRING(iovec[n++], mid); } + m = n; + + va_start(ap, format); + assert_se(log_format_iovec(iovec, ELEMENTSOF(iovec), &n, false, 0, format, ap) >= 0); + va_end(ap); + ucred.pid = getpid(); ucred.uid = getuid(); ucred.gid = getgid(); dispatch_message_real(s, iovec, n, ELEMENTSOF(iovec), &ucred, NULL, NULL, 0, NULL, LOG_INFO, 0); + + while (m < n) + free(iovec[m++].iov_base); } void server_dispatch_message( @@ -901,7 +906,8 @@ void server_dispatch_message( /* Write a suppression message if we suppressed something */ if (rl > 1) server_driver_message(s, SD_MESSAGE_JOURNAL_DROPPED, - "Suppressed %u messages from %s", rl - 1, path); + LOG_MESSAGE("Suppressed %u messages from %s", rl - 1, path), + NULL); finish: dispatch_message_real(s, iovec, n, m, ucred, tv, label, label_len, unit_id, priority, object_pid); @@ -1073,7 +1079,11 @@ finish: sd_journal_close(j); - server_driver_message(s, SD_ID128_NULL, "Time spent on flushing to /var is %s for %u entries.", format_timespan(ts, sizeof(ts), now(CLOCK_MONOTONIC) - start, 0), n); + server_driver_message(s, SD_ID128_NULL, + LOG_MESSAGE("Time spent on flushing to /var is %s for %u entries.", + format_timespan(ts, sizeof(ts), now(CLOCK_MONOTONIC) - start, 0), + n), + NULL); return r; } diff --git a/src/journal/journald-server.h b/src/journal/journald-server.h index 1822765228..0ef83d161f 100644 --- a/src/journal/journald-server.h +++ b/src/journal/journald-server.h @@ -157,9 +157,10 @@ struct Server { #define N_IOVEC_KERNEL_FIELDS 64 #define N_IOVEC_UDEV_FIELDS 32 #define N_IOVEC_OBJECT_FIELDS 12 +#define N_IOVEC_PAYLOAD_FIELDS 1 void server_dispatch_message(Server *s, struct iovec *iovec, unsigned n, unsigned m, const struct ucred *ucred, const struct timeval *tv, const char *label, size_t label_len, const char *unit_id, int priority, pid_t object_pid); -void server_driver_message(Server *s, sd_id128_t message_id, const char *format, ...) _printf_(3,4); +void server_driver_message(Server *s, sd_id128_t message_id, const char *format, ...) _printf_(3,0) _sentinel_; /* gperf lookup function */ const struct ConfigPerfItem* journald_gperf_lookup(const char *key, unsigned length); diff --git a/src/journal/journald-syslog.c b/src/journal/journald-syslog.c index 0be73088e2..9f2ccdcc77 100644 --- a/src/journal/journald-syslog.c +++ b/src/journal/journald-syslog.c @@ -448,7 +448,10 @@ void server_maybe_warn_forward_syslog_missed(Server *s) { if (s->last_warn_forward_syslog_missed + WARN_FORWARD_SYSLOG_MISSED_USEC > n) return; - server_driver_message(s, SD_MESSAGE_FORWARD_SYSLOG_MISSED, "Forwarding to syslog missed %u messages.", s->n_forward_syslog_missed); + server_driver_message(s, SD_MESSAGE_FORWARD_SYSLOG_MISSED, + LOG_MESSAGE("Forwarding to syslog missed %u messages.", + s->n_forward_syslog_missed), + NULL); s->n_forward_syslog_missed = 0; s->last_warn_forward_syslog_missed = n; diff --git a/src/journal/journald.c b/src/journal/journald.c index b9f5c099e1..293b788d03 100644 --- a/src/journal/journald.c +++ b/src/journal/journald.c @@ -58,7 +58,9 @@ int main(int argc, char *argv[]) { server_flush_dev_kmsg(&server); log_debug("systemd-journald running as pid "PID_FMT, getpid()); - server_driver_message(&server, SD_MESSAGE_JOURNAL_START, "Journal started"); + server_driver_message(&server, SD_MESSAGE_JOURNAL_START, + LOG_MESSAGE("Journal started"), + NULL); for (;;) { usec_t t = USEC_INFINITY, n; @@ -109,7 +111,9 @@ int main(int argc, char *argv[]) { } log_debug("systemd-journald stopped as pid "PID_FMT, getpid()); - server_driver_message(&server, SD_MESSAGE_JOURNAL_STOP, "Journal stopped"); + server_driver_message(&server, SD_MESSAGE_JOURNAL_STOP, + LOG_MESSAGE("Journal stopped"), + NULL); finish: server_done(&server); From 282c5c4e422cb6e6685c870946d8b9bdf0879ad1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Tue, 10 Nov 2015 07:44:19 -0500 Subject: [PATCH 3/4] journald: use structured message + catalog entry for disk usage The format of the journald disk usage log entry was changed back and forth a few times. It is annoying to have a very verbose message, but if it is short it is hard to understand. But we have a tool for this, the catalogue. $ journalctl -x -u systemd-journald Jan 23 18:48:50 rawhide systemd-journald[891]: Runtime journal (/run/log/journal/) is 8.0M, max 196.2M, 188.2M free. -- Subject: Disk space used by the journal -- Defined-By: systemd -- Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel -- -- Runtime journal (/run/log/journal/) is currently using 8.0M. -- Maximum allowed usage is set to 196.2M. -- Leaving at least 294.3M free (of currently available 1.9G of disk space). -- Enforced usage limit is thus 196.2M, of which 188.2M are still available. -- -- The limits controlling how much disk space is used by the journal may -- be configured with SystemMaxUse=, SystemKeepFree=, SystemMaxFileSize=, -- RuntimeMaxUse=, RuntimeKeepFree=, RuntimeMaxFileSize= settings in -- /etc/systemd/journald.conf. See journald.conf(5) for details. Jan 23 18:48:50 rawhide systemd-journald[891]: System journal (/var/log/journal/) is 480.1M, max 1.6G, 1.2G free. -- Subject: Disk space used by the journal -- Defined-By: systemd -- Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel -- -- System journal (/var/log/journal/) is currently using 480.1M. -- Maximum allowed usage is set to 1.6G. -- Leaving at least 2.5G free (of currently available 5.8G of disk space). -- Enforced usage limit is thus 1.6G, of which 1.2G are still available. -- -- The limits controlling how much disk space is used by the journal may -- be configured with SystemMaxUse=, SystemKeepFree=, SystemMaxFileSize=, -- RuntimeMaxUse=, RuntimeKeepFree=, RuntimeMaxFileSize= settings in -- /etc/systemd/journald.conf. See journald.conf(5) for details. --- catalog/systemd.catalog | 15 +++++++++++++++ src/journal/journald-server.c | 34 ++++++++++++++++++++++------------ src/journal/journald-server.h | 2 +- 3 files changed, 38 insertions(+), 13 deletions(-) diff --git a/catalog/systemd.catalog b/catalog/systemd.catalog index 4488c835a8..2ca9beb045 100644 --- a/catalog/systemd.catalog +++ b/catalog/systemd.catalog @@ -38,6 +38,21 @@ Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel The system journal process has shut down and closed all currently active journal files. +-- ec387f577b844b8fa948f33cad9a75e6 +Subject: Disk space used by the journal +Defined-By: systemd +Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel + +@JOURNAL_NAME@ (@JOURNAL_PATH@) is currently using @CURRENT_USE_PRETTY@. +Maximum allowed usage is set to @MAX_USE_PRETTY@. +Leaving at least @DISK_KEEP_FREE_PRETTY@ free (of currently available @DISK_AVAILABLE_PRETTY@ of disk space). +Enforced usage limit is thus @LIMIT_PRETTY@, of which @AVAILABLE_PRETTY@ are still available. + +The limits controlling how much disk space is used by the journal may +be configured with SystemMaxUse=, SystemKeepFree=, SystemMaxFileSize=, +RuntimeMaxUse=, RuntimeKeepFree=, RuntimeMaxFileSize= settings in +/etc/systemd/journald.conf. See journald.conf(5) for details. + -- a596d6fe7bfa4994828e72309e95d61e Subject: Messages from a service have been suppressed Defined-By: systemd diff --git a/src/journal/journald-server.c b/src/journal/journald-server.c index 6df71953e8..1c72976600 100644 --- a/src/journal/journald-server.c +++ b/src/journal/journald-server.c @@ -163,20 +163,30 @@ static int determine_space_for( if (verbose) { char fb1[FORMAT_BYTES_MAX], fb2[FORMAT_BYTES_MAX], fb3[FORMAT_BYTES_MAX], fb4[FORMAT_BYTES_MAX], fb5[FORMAT_BYTES_MAX], fb6[FORMAT_BYTES_MAX]; + format_bytes(fb1, sizeof(fb1), sum); + format_bytes(fb2, sizeof(fb2), metrics->max_use); + format_bytes(fb3, sizeof(fb3), metrics->keep_free); + format_bytes(fb4, sizeof(fb4), ss_avail); + format_bytes(fb5, sizeof(fb5), s->cached_space_limit); + format_bytes(fb6, sizeof(fb6), s->cached_space_available); server_driver_message(s, SD_MESSAGE_JOURNAL_USAGE, - LOG_MESSAGE( - "%s (%s) is currently using %s.\n" - "Maximum allowed usage is set to %s.\n" - "Leaving at least %s free (of currently available %s of space).\n" - "Enforced usage limit is thus %s, of which %s are still available.", - name, path, - format_bytes(fb1, sizeof(fb1), sum), - format_bytes(fb2, sizeof(fb2), metrics->max_use), - format_bytes(fb3, sizeof(fb3), metrics->keep_free), - format_bytes(fb4, sizeof(fb4), ss_avail), - format_bytes(fb5, sizeof(fb5), s->cached_space_limit), - format_bytes(fb6, sizeof(fb6), s->cached_space_available)), + LOG_MESSAGE("%s (%s) is %s, max %s, %s free.", + name, path, fb1, fb5, fb6), + "JOURNAL_NAME=%s", name, + "JOURNAL_PATH=%s", path, + "CURRENT_USE=%"PRIu64, sum, + "CURRENT_USE_PRETTY=%s", fb1, + "MAX_USE=%"PRIu64, metrics->max_use, + "MAX_USE_PRETTY=%s", fb2, + "DISK_KEEP_FREE=%"PRIu64, metrics->keep_free, + "DISK_KEEP_FREE_PRETTY=%s", fb3, + "DISK_AVAILABLE=%"PRIu64, ss_avail, + "DISK_AVAILABLE_PRETTY=%s", fb4, + "LIMIT=%"PRIu64, s->cached_space_limit, + "LIMIT_PRETTY=%s", fb5, + "AVAILABLE=%"PRIu64, s->cached_space_available, + "AVAILABLE_PRETTY=%s", fb6, NULL); } diff --git a/src/journal/journald-server.h b/src/journal/journald-server.h index 0ef83d161f..49bbee0646 100644 --- a/src/journal/journald-server.h +++ b/src/journal/journald-server.h @@ -157,7 +157,7 @@ struct Server { #define N_IOVEC_KERNEL_FIELDS 64 #define N_IOVEC_UDEV_FIELDS 32 #define N_IOVEC_OBJECT_FIELDS 12 -#define N_IOVEC_PAYLOAD_FIELDS 1 +#define N_IOVEC_PAYLOAD_FIELDS 15 void server_dispatch_message(Server *s, struct iovec *iovec, unsigned n, unsigned m, const struct ucred *ucred, const struct timeval *tv, const char *label, size_t label_len, const char *unit_id, int priority, pid_t object_pid); void server_driver_message(Server *s, sd_id128_t message_id, const char *format, ...) _printf_(3,0) _sentinel_; From 32917e33882778cf2ec6dd54b1e1082266fb072e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Wed, 11 Nov 2015 07:54:50 -0500 Subject: [PATCH 4/4] journald: restore oom safety v2: - use xsprintf --- src/journal/journald-server.c | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/src/journal/journald-server.c b/src/journal/journald-server.c index 1c72976600..f55e46382d 100644 --- a/src/journal/journald-server.c +++ b/src/journal/journald-server.c @@ -67,6 +67,7 @@ #include "selinux-util.h" #include "signal-util.h" #include "socket-util.h" +#include "stdio-util.h" #include "string-table.h" #include "string-util.h" #include "user-util.h" @@ -823,6 +824,7 @@ void server_driver_message(Server *s, sd_id128_t message_id, const char *format, char mid[11 + 32 + 1]; struct iovec iovec[N_IOVEC_META_FIELDS + 5 + N_IOVEC_PAYLOAD_FIELDS]; unsigned n = 0, m; + int r; va_list ap; struct ucred ucred = {}; @@ -832,8 +834,8 @@ void server_driver_message(Server *s, sd_id128_t message_id, const char *format, IOVEC_SET_STRING(iovec[n++], "SYSLOG_FACILITY=3"); IOVEC_SET_STRING(iovec[n++], "SYSLOG_IDENTIFIER=systemd-journald"); - IOVEC_SET_STRING(iovec[n++], "PRIORITY=6"); IOVEC_SET_STRING(iovec[n++], "_TRANSPORT=driver"); + IOVEC_SET_STRING(iovec[n++], "PRIORITY=6"); if (!sd_id128_equal(message_id, SD_ID128_NULL)) { snprintf(mid, sizeof(mid), LOG_MESSAGE_ID(message_id)); @@ -843,17 +845,31 @@ void server_driver_message(Server *s, sd_id128_t message_id, const char *format, m = n; va_start(ap, format); - assert_se(log_format_iovec(iovec, ELEMENTSOF(iovec), &n, false, 0, format, ap) >= 0); + r = log_format_iovec(iovec, ELEMENTSOF(iovec), &n, false, 0, format, ap); + /* Error handling below */ va_end(ap); ucred.pid = getpid(); ucred.uid = getuid(); ucred.gid = getgid(); - dispatch_message_real(s, iovec, n, ELEMENTSOF(iovec), &ucred, NULL, NULL, 0, NULL, LOG_INFO, 0); + if (r >= 0) + dispatch_message_real(s, iovec, n, ELEMENTSOF(iovec), &ucred, NULL, NULL, 0, NULL, LOG_INFO, 0); while (m < n) free(iovec[m++].iov_base); + + if (r < 0) { + /* We failed to format the message. Emit a warning instead. */ + char buf[LINE_MAX]; + + xsprintf(buf, "MESSAGE=Entry printing failed: %s", strerror(-r)); + + n = 3; + IOVEC_SET_STRING(iovec[n++], "PRIORITY=4"); + IOVEC_SET_STRING(iovec[n++], buf); + dispatch_message_real(s, iovec, n, ELEMENTSOF(iovec), &ucred, NULL, NULL, 0, NULL, LOG_INFO, 0); + } } void server_dispatch_message(