summaryrefslogtreecommitdiff
path: root/src/shared
diff options
context:
space:
mode:
Diffstat (limited to 'src/shared')
-rw-r--r--src/shared/log.c118
-rw-r--r--src/shared/log.h64
2 files changed, 160 insertions, 22 deletions
diff --git a/src/shared/log.c b/src/shared/log.c
index 4fc430eed1..67a3e1b843 100644
--- a/src/shared/log.c
+++ b/src/shared/log.c
@@ -658,11 +658,127 @@ _noreturn_ void log_assert_failed_unreachable(const char *text, const char *file
log_assert(text, file, line, func, "Code should not be reached '%s' at %s:%u, function %s(). Aborting.");
}
-int __log_oom(const char *file, int line, const char *func) {
+int log_oom_internal(const char *file, int line, const char *func) {
log_meta(LOG_ERR, file, line, func, "Out of memory.");
return -ENOMEM;
}
+int log_struct_internal(
+ int level,
+ const char *file,
+ int line,
+ const char *func,
+ const char *format, ...) {
+
+ int saved_errno;
+ va_list ap;
+ int r;
+
+ if (_likely_(LOG_PRI(level) > log_max_level))
+ return 0;
+
+ if (log_target == LOG_TARGET_NULL)
+ return 0;
+
+ if ((level & LOG_FACMASK) == 0)
+ level = log_facility | LOG_PRI(level);
+
+ saved_errno = errno;
+
+ if ((log_target == LOG_TARGET_AUTO ||
+ log_target == LOG_TARGET_JOURNAL_OR_KMSG ||
+ log_target == LOG_TARGET_JOURNAL) &&
+ journal_fd >= 0) {
+
+ char header[LINE_MAX];
+ struct iovec iovec[17];
+ unsigned n = 0, i;
+ struct msghdr mh;
+ const char nl = '\n';
+
+ /* If the journal is available do structured logging */
+
+ snprintf(header, sizeof(header),
+ "PRIORITY=%i\n"
+ "SYSLOG_FACILITY=%i\n"
+ "CODE_FILE=%s\n"
+ "CODE_LINE=%i\n"
+ "CODE_FUNCTION=%s\n"
+ "SYSLOG_IDENTIFIER=%s\n",
+ LOG_PRI(level),
+ LOG_FAC(level),
+ file,
+ line,
+ func,
+ program_invocation_short_name);
+ char_array_0(header);
+
+ zero(iovec);
+ IOVEC_SET_STRING(iovec[n++], header);
+
+ va_start(ap, format);
+ while (format && n + 1 < ELEMENTSOF(iovec)) {
+ char *buf;
+
+ if (vasprintf(&buf, format, ap) < 0) {
+ r = -ENOMEM;
+ goto finish;
+ }
+
+ IOVEC_SET_STRING(iovec[n++], buf);
+
+ iovec[n].iov_base = (char*) &nl;
+ iovec[n].iov_len = 1;
+ n++;
+
+ format = va_arg(ap, char *);
+ }
+ va_end(ap);
+
+ zero(mh);
+ mh.msg_iov = iovec;
+ mh.msg_iovlen = n;
+
+ if (sendmsg(journal_fd, &mh, MSG_NOSIGNAL) < 0)
+ r = -errno;
+ else
+ r = 1;
+
+ finish:
+ for (i = 1; i < n; i += 2)
+ free(iovec[i].iov_base);
+
+ } else {
+ char buf[LINE_MAX];
+ bool found = false;
+
+ /* Fallback if journal logging is not available */
+
+ va_start(ap, format);
+ while (format) {
+
+ vsnprintf(buf, sizeof(buf), format, ap);
+ char_array_0(buf);
+
+ if (startswith(buf, "MESSAGE=")) {
+ found = true;
+ break;
+ }
+
+ format = va_arg(ap, char *);
+ }
+ va_end(ap);
+
+ if (found)
+ r = log_dispatch(level, file, line, func, buf + 8);
+ else
+ r = -EINVAL;
+ }
+
+ errno = saved_errno;
+ return r;
+}
+
int log_set_target_from_string(const char *e) {
LogTarget t;
diff --git a/src/shared/log.h b/src/shared/log.h
index ab894df172..0c60b7671b 100644
--- a/src/shared/log.h
+++ b/src/shared/log.h
@@ -70,30 +70,51 @@ void log_close_console(void);
void log_parse_environment(void);
int log_meta(
- int level,
- const char*file,
- int line,
- const char *func,
- const char *format, ...) _printf_attr_(5,6);
+ int level,
+ const char*file,
+ int line,
+ const char *func,
+ const char *format, ...) _printf_attr_(5,6);
int log_metav(
- int level,
- const char*file,
- int line,
- const char *func,
- const char *format,
- va_list ap);
-
-_noreturn_ void log_assert_failed(const char *text, const char *file, int line, const char *func);
-_noreturn_ void log_assert_failed_unreachable(const char *text, const char *file, int line, const char *func);
+ int level,
+ const char*file,
+ int line,
+ const char *func,
+ const char *format,
+ va_list ap);
+
+int log_struct_internal(
+ int level,
+ const char *file,
+ int line,
+ const char *func,
+ const char *format, ...) _sentinel_;
+
+int log_oom_internal(
+ const char *file,
+ int line,
+ const char *func);
/* This modifies the buffer passed! */
int log_dump_internal(
- int level,
- const char*file,
- int line,
- const char *func,
- char *buffer);
+ int level,
+ const char*file,
+ int line,
+ const char *func,
+ char *buffer);
+
+_noreturn_ void log_assert_failed(
+ const char *text,
+ const char *file,
+ int line,
+ const char *func);
+
+_noreturn_ void log_assert_failed_unreachable(
+ const char *text,
+ const char *file,
+ int line,
+ const char *func);
#define log_full(level, ...) log_meta(level, __FILE__, __LINE__, __func__, __VA_ARGS__)
@@ -103,8 +124,9 @@ int log_dump_internal(
#define log_warning(...) log_meta(LOG_WARNING, __FILE__, __LINE__, __func__, __VA_ARGS__)
#define log_error(...) log_meta(LOG_ERR, __FILE__, __LINE__, __func__, __VA_ARGS__)
-int __log_oom(const char *file, int line, const char *func);
-#define log_oom() __log_oom(__FILE__, __LINE__, __func__)
+#define log_struct(level, ...) log_struct_internal(level, __FILE__, __LINE__, __func__, __VA_ARGS__)
+
+#define log_oom() log_oom_internal(__FILE__, __LINE__, __func__)
/* This modifies the buffer passed! */
#define log_dump(level, buffer) log_dump_internal(level, __FILE__, __LINE__, __func__, buffer)