chiark / gitweb /
journal: add sd_journal_perror() to API
authorLennart Poettering <lennart@poettering.net>
Tue, 31 Jul 2012 14:09:01 +0000 (16:09 +0200)
committerLennart Poettering <lennart@poettering.net>
Wed, 1 Aug 2012 17:53:23 +0000 (19:53 +0200)
Makefile.am
configure.ac
man/sd_journal_print.xml
man/systemd.journal-fields.xml
src/journal/journal-send.c
src/journal/libsystemd-journal.sym
src/journal/test-journal-send.c
src/systemd/sd-journal.h

index cf37ebe627c38509f9218c8a9cb68ad0f3a8f8d1..77aed920a5aa705c010b71cc51296bc09e52bd7b 100644 (file)
@@ -557,6 +557,7 @@ MANPAGES_ALIAS = \
        man/sd_journal_printv.3 \
        man/sd_journal_send.3 \
        man/sd_journal_sendv.3 \
+       man/sd_journal_perror.3 \
        man/SD_JOURNAL_SUPPRESS_LOCATION.3 \
        man/sd_journal_open_directory.3 \
        man/sd_journal_close.3 \
@@ -624,6 +625,7 @@ man/sd_id128_get_boot.3: man/sd_id128_get_machine.3
 man/sd_journal_printv.3: man/sd_journal_print.3
 man/sd_journal_send.3: man/sd_journal_print.3
 man/sd_journal_sendv.3: man/sd_journal_print.3
+man/sd_journal_perror.3: man/sd_journal_print.3
 man/SD_JOURNAL_SUPPRESS_LOCATION.3: man/sd_journal_print.3
 man/sd_journal_open_directory.3: man/sd_journal_open.3
 man/sd_journal_close.3: man/sd_journal_open.3
index cef2539e27c03e6beaa110468204de0d3cabc6f4..51452982045bf047a802d0cc0401a57b0f377fb1 100644 (file)
@@ -89,7 +89,6 @@ CC_CHECK_FLAGS_APPEND([with_cflags], [CFLAGS], [\
         -W \
         -Wextra \
         -Wno-inline \
-        -Wvla \
         -Wundef \
         -Wformat=2 \
         -Wlogical-op \
index dfe99192e7e7a28e5fd7b61532a8d4cd4aabf702..7eac6c8192567749af637c1d8b5cd3aaedc24daf 100644 (file)
@@ -47,6 +47,7 @@
                 <refname>sd_journal_printv</refname>
                 <refname>sd_journal_send</refname>
                 <refname>sd_journal_sendv</refname>
+                <refname>sd_journal_perror</refname>
                 <refname>SD_JOURNAL_SUPPRESS_LOCATION</refname>
                 <refpurpose>Submit log entries to the journal</refpurpose>
         </refnamediv>
                                 <paramdef>int <parameter>n</parameter></paramdef>
                         </funcprototype>
 
+                        <funcprototype>
+                                <funcdef>int <function>sd_journal_perror</function></funcdef>
+                                <paramdef>const char* <parameter>message</parameter></paramdef>
+                        </funcprototype>
+
                 </funcsynopsis>
         </refsynopsisdiv>
 
                 particularly useful to submit binary objects to the
                 journal where that is necessary.</para>
 
+                <para><function>sd_journal_perror()</function> is a
+                similar to
+                <citerefentry><refentrytitle>perror</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+                and writes a message to the journal that consists of
+                the passed string, suffixed with ": " and a human
+                readable representation of the current error code
+                stored in
+                <citerefentry><refentrytitle>errno</refentrytitle><manvolnum>3</manvolnum></citerefentry>. If
+                the message string is passed as NULL or empty string
+                only the error string representation will be written,
+                prefixed with nothing. An additional journal field
+                ERRNO= is included in the entry containing the numeric
+                error code formatted as decimal string. The log
+                priority used is <literal>LOG_ERR</literal> (3).</para>
+
                 <para>Note that <function>sd_journal_send()</function>
                 is a wrapper around
                 <function>sd_journal_sendv()</function> to make it
@@ -191,8 +212,10 @@ sd_journal_send("MESSAGE=Hello World, this is PID %lu!", (unsigned long) getpid(
         <refsect1>
                 <title>Return Value</title>
 
-                <para>The four calls return 0 on success or a
-                negative errno-style error code.</para>
+                <para>The four calls return 0 on success or a negative
+                errno-style error code. The
+                <citerefentry><refentrytitle>errno</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+                variable itself is not altered.</para>
         </refsect1>
 
         <refsect1>
@@ -217,6 +240,8 @@ sd_journal_send("MESSAGE=Hello World, this is PID %lu!", (unsigned long) getpid(
                         <citerefentry><refentrytitle>sd-journal</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
                         <citerefentry><refentrytitle>sd_journal_stream_fd</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
                         <citerefentry><refentrytitle>syslog</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+                        <citerefentry><refentrytitle>perror</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
+                        <citerefentry><refentrytitle>errno</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
                         <citerefentry><refentrytitle>systemd.journal-fields</refentrytitle><manvolnum>7</manvolnum></citerefentry>
                 </para>
         </refsect1>
index 6a9fd9d85cdaf80efefd08fbf732fc0c14db6dec..59bb8ad70a26f80dc6c7e1b2fc84b615af693ec4 100644 (file)
                                 </listitem>
                         </varlistentry>
 
+                        <varlistentry>
+                                <term>ERRNO=</term>
+                                <listitem>
+                                        <para>The low-level Unix error
+                                        number causing this entry, if
+                                        any. Contains the numeric
+                                        value of
+                                        <citerefentry><refentrytitle>errno</refentrytitle><manvolnum>3</manvolnum></citerefentry>
+                                        formatted as decimal
+                                        string.</para>
+                                </listitem>
+                        </varlistentry>
+
                         <varlistentry>
                                 <term>SYSLOG_FACILITY=</term>
                                 <term>SYSLOG_IDENTIFIER=</term>
index bc44828e1c0e0ea724d496d397d6fa6f5928e178..d0f3b725ff5ee9a3a1d97e0fc5fe33f4a7fc11f8 100644 (file)
@@ -73,8 +73,11 @@ _public_ int sd_journal_print(int priority, const char *format, ...) {
 }
 
 _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;
@@ -340,6 +343,63 @@ finish:
         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;
@@ -489,7 +549,11 @@ finish:
         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;
@@ -514,3 +578,24 @@ _public_ int sd_journal_sendv_with_location(const char *file, const char *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);
+        f = alloca(fl + 10);
+        memcpy(f, "CODE_FUNC=", 10);
+        memcpy(f + 10, func, fl + 1);
+
+        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);
+}
index c33474aeab7c9e3e4136dab0548059b4757999e6..770f89933344c3a2228dd631713540298653fa84 100644 (file)
@@ -63,4 +63,6 @@ global:
         sd_journal_wait;
         sd_journal_open_directory;
         sd_journal_add_disjunction;
+        sd_journal_perror;
+        sd_journal_perror_with_location;
 } LIBSYSTEMD_JOURNAL_184;
index 9d376d1e56ec81438052fc40c44ee8aa506bdc8f..e708fa440650d76d1e3e219efe024bddf6229751 100644 (file)
@@ -32,5 +32,10 @@ int main(int argc, char *argv[]) {
                         "VALUE=%i", 7,
                         NULL);
 
+        errno = ENOENT;
+        sd_journal_perror("Foobar");
+
+        sd_journal_perror("");
+
         return 0;
 }
index e70f575ce9c6129d8fa42c09dcc2e43746df6390..de1c8f38f266303a98f8f5b044c6c70badc6ccf0 100644 (file)
@@ -41,12 +41,14 @@ int sd_journal_print(int priority, const char *format, ...) __attribute__ ((form
 int sd_journal_printv(int priority, const char *format, va_list ap);
 int sd_journal_send(const char *format, ...) __attribute__((sentinel));
 int sd_journal_sendv(const struct iovec *iov, int n);
+int sd_journal_perror(const char *message);
 
 /* Used by the macros below. Don't call this directly. */
 int sd_journal_print_with_location(int priority, const char *file, const char *line, const char *func, const char *format, ...) __attribute__ ((format (printf, 5, 6)));
 int sd_journal_printv_with_location(int priority, const char *file, const char *line, const char *func, const char *format, va_list ap);
 int sd_journal_send_with_location(const char *file, const char *line, const char *func, const char *format, ...) __attribute__((sentinel));
 int sd_journal_sendv_with_location(const char *file, const char *line, const char *func, const struct iovec *iov, int n);
+int sd_journal_perror_with_location(const char *file, const char *line, const char *func, const char *message);
 
 /* implicitly add code location to messages sent, if this is enabled */
 #ifndef SD_JOURNAL_SUPPRESS_LOCATION
@@ -58,6 +60,7 @@ int sd_journal_sendv_with_location(const char *file, const char *line, const cha
 #define sd_journal_printv(priority, format, ap) sd_journal_printv_with_location(priority, "CODE_FILE=" __FILE__, "CODE_LINE=" _sd_STRINGIFY(__LINE__), __func__, format, ap)
 #define sd_journal_send(...) sd_journal_send_with_location("CODE_FILE=" __FILE__, "CODE_LINE=" _sd_STRINGIFY(__LINE__), __func__, __VA_ARGS__)
 #define sd_journal_sendv(iovec, n) sd_journal_sendv_with_location("CODE_FILE=" __FILE__, "CODE_LINE=" _sd_STRINGIFY(__LINE__), __func__, iovec, n)
+#define sd_journal_perror(message) sd_journal_perror_with_location("CODE_FILE=" __FILE__, "CODE_LINE=" _sd_STRINGIFY(__LINE__), __func__, message)
 
 #endif