#include <stddef.h>
#include <unistd.h>
#include <fcntl.h>
+#include <printf.h>
#define SD_JOURNAL_SUPPRESS_LOCATION
}
_public_ int sd_journal_printv(int priority, const char *format, va_list ap) {
- char buffer[8 + LINE_MAX], p[11];
- struct iovec iov[2];
+
+ /* FIXME: Instead of limiting things to LINE_MAX we could do a
+ C99 variable-length array on the stack here in a loop. */
+
+ char buffer[8 + LINE_MAX], p[11]; struct iovec iov[2];
if (priority < 0 || priority > 7)
return -EINVAL;
while (format) {
struct iovec *c;
char *buffer;
+ va_list aq;
if (i >= n) {
n = MAX(i*2, 4);
iov = c;
}
- if (vasprintf(&buffer, format, ap) < 0) {
+ va_copy(aq, ap);
+ if (vasprintf(&buffer, format, aq) < 0) {
+ va_end(aq);
r = -ENOMEM;
goto fail;
}
+ va_end(aq);
+
+ VA_FORMAT_ADVANCE(format, ap);
IOVEC_SET_STRING(iov[i++], buffer);
return r;
}
+static int fill_iovec_perror_and_send(const char *message, int skip, struct iovec iov[]) {
+ size_t n, k, r;
+ int saved_errno;
+
+ saved_errno = errno;
+
+ k = isempty(message) ? 0 : strlen(message) + 2;
+ n = 8 + k + 256 + 1;
+
+ for (;;) {
+ char buffer[n];
+ char* j;
+
+ errno = 0;
+ j = strerror_r(saved_errno, buffer + 8 + k, n - 8 - k);
+ if (errno == 0) {
+ char error[6 + 10 + 1]; /* for a 32bit value */
+
+ if (j != buffer + 8 + k)
+ memmove(buffer + 8 + k, j, strlen(j)+1);
+
+ memcpy(buffer, "MESSAGE=", 8);
+
+ if (k > 0) {
+ memcpy(buffer + 8, message, k - 2);
+ memcpy(buffer + 8 + k - 2, ": ", 2);
+ }
+
+ snprintf(error, sizeof(error), "ERRNO=%u", saved_errno);
+ char_array_0(error);
+
+ IOVEC_SET_STRING(iov[skip+0], "PRIORITY=3");
+ IOVEC_SET_STRING(iov[skip+1], buffer);
+ IOVEC_SET_STRING(iov[skip+2], error);
+
+ r = sd_journal_sendv(iov, skip + 3);
+
+ errno = saved_errno;
+ return r;
+ }
+
+ if (errno != ERANGE) {
+ r = -errno;
+ errno = saved_errno;
+ return r;
+ }
+
+ n *= 2;
+ }
+}
+
+_public_ int sd_journal_perror(const char *message) {
+ struct iovec iovec[3];
+
+ return fill_iovec_perror_and_send(message, 0, iovec);
+}
+
_public_ int sd_journal_stream_fd(const char *identifier, int priority, int level_prefix) {
union sockaddr_union sa;
int fd;
identifier = "";
l = strlen(identifier);
- header = alloca(l + 1 + 2 + 2 + 2 + 2 + 2);
+ header = alloca(l + 1 + 1 + 2 + 2 + 2 + 2 + 2);
memcpy(header, identifier, l);
header[l++] = '\n';
+ header[l++] = '\n'; /* unit id */
header[l++] = '0' + priority;
header[l++] = '\n';
header[l++] = '0' + !!level_prefix;
/* func is initialized from __func__ which is not a macro, but
* a static const char[], hence cannot easily be prefixed with
* CODE_FUNC=, hence let's do it manually here. */
- fl = strlen(func);
+ fl = strlen(func) + 1;
f = alloca(fl + 10);
memcpy(f, "CODE_FUNC=", 10);
- memcpy(f + 10, func, fl + 1);
+ memcpy(f + 10, func, fl);
zero(iov);
IOVEC_SET_STRING(iov[0], buffer);
goto finish;
}
- fl = strlen(func);
+ fl = strlen(func) + 1;
f = alloca(fl + 10);
memcpy(f, "CODE_FUNC=", 10);
- memcpy(f + 10, func, fl + 1);
+ memcpy(f + 10, func, fl);
IOVEC_SET_STRING(iov[0], file);
IOVEC_SET_STRING(iov[1], line);
return r;
}
-_public_ int sd_journal_sendv_with_location(const char *file, const char *line, const char *func, const struct iovec *iov, int n) {
+_public_ int sd_journal_sendv_with_location(
+ const char *file, const char *line,
+ const char *func,
+ const struct iovec *iov, int n) {
+
struct iovec *niov;
char *f;
size_t fl;
niov = alloca(sizeof(struct iovec) * (n + 3));
memcpy(niov, iov, sizeof(struct iovec) * n);
- fl = strlen(func);
+ fl = strlen(func) + 1;
f = alloca(fl + 10);
memcpy(f, "CODE_FUNC=", 10);
- memcpy(f + 10, func, fl + 1);
+ memcpy(f + 10, func, fl);
IOVEC_SET_STRING(niov[n++], file);
IOVEC_SET_STRING(niov[n++], line);
return sd_journal_sendv(niov, n);
}
+
+_public_ int sd_journal_perror_with_location(
+ const char *file, const char *line,
+ const char *func,
+ const char *message) {
+
+ struct iovec iov[6];
+ size_t fl;
+ char *f;
+
+ fl = strlen(func) + 1;
+ f = alloca(fl + 10);
+ memcpy(f, "CODE_FUNC=", 10);
+ memcpy(f + 10, func, fl);
+
+ IOVEC_SET_STRING(iov[0], file);
+ IOVEC_SET_STRING(iov[1], line);
+ IOVEC_SET_STRING(iov[2], f);
+
+ return fill_iovec_perror_and_send(message, 3, iov);
+}