This adds a configurable option 'FEATURE_SYSLOGD_ISO8601FMT' enabling
a command line option ('-I', with semantics similar to 'date') that
directs syslogd to log timestamps in ISO 8601 format.

Precision in seconds (the default), milliseconds, and microseconds are
supported. Without the 'FEATURE_SYSLOGD_UTC' configuration and its
'-u' option, outputs are of the form:

  YYYY-MM-DDThh:mm:ss±hhmm (seconds)
  YYYY-MM-DDThh:mm:ss.sss±hhmm (milliseconds)
  YYYY-MM-DDThh:mm:ss.uuuuuu±hhmm (microseconds)

with the 'FEATURE_SYSLOGD_UTC' configuration and its '-u' option,
outputs are of the form:

  YYYY-MM-DDThh:mm:ssZ (seconds)
  YYYY-MM-DDThh:mm:ss.sssZ (milliseconds)
  YYYY-MM-DDThh:mm:ss.uuuuuuZ (microseconds)

Signed-off-by: Grant Erickson <gerick...@nuovations.com>
---
 sysklogd/syslogd.c | 157 ++++++++++++++++++++++++++++++++++-----------
 1 file changed, 118 insertions(+), 39 deletions(-)

diff --git a/sysklogd/syslogd.c b/sysklogd/syslogd.c
index 287b70e45d19..f05fac6d8a92 100644
--- a/sysklogd/syslogd.c
+++ b/sysklogd/syslogd.c
@@ -44,6 +44,15 @@
 //config:      syslogd to log timestamps in Coordinated Universal Time
 //config:      (UTC) rather than in local time.
 //config:
+//config:config FEATURE_SYSLOGD_ISO8601FMT
+//config:      bool "Log timestamps in ISO 8601 format"
+//config:      default n
+//config:      depends on SYSLOGD
+//config:      help
+//config:      This enables a command line option ('-I') that directs
+//config:      syslogd to log timestamps in ISO 8601 format with second,
+//config:      millisecond, or microsecond resolution.
+//config:
 //config:config FEATURE_REMOTE_LOG
 //config:      bool "Remote Log support"
 //config:      default y
@@ -159,6 +168,10 @@
 //usage:       IF_FEATURE_SYSLOGD_UTC(
 //usage:     "\n       -u              Log timestamps in Coordinated Universal 
Time (UTC)"
 //usage:       )
+//usage:       IF_FEATURE_SYSLOGD_ISO8601FMT(
+//usage:     "\n       -I[SPEC]        Log timestamps in ISO 8601 format"
+//usage:     "\n                       SPEC=seconds (default), ms, or us"
+//usage:       )
 //usage:     "\n       -t              Strip client-generated timestamps"
 //usage:       IF_FEATURE_SYSLOGD_DUP(
 //usage:     "\n       -D              Drop duplicates"
@@ -272,6 +285,9 @@ IF_FEATURE_SYSLOGD_CFG( \
 IF_FEATURE_KMSG_SYSLOG( \
        int kmsgfd; \
        int primask; \
+) \
+IF_FEATURE_SYSLOGD_ISO8601FMT( \
+       int iso8601fmt; \
 )
 
 struct init_globals {
@@ -298,7 +314,7 @@ struct globals {
        /* ...then sprintf into printbuf, adding timestamp (15 or 19 chars),
         * host (64), fac.prio (20) to the message */
        /* (growth by: 15 + 64 + 20 + delims = ~110) */
-       char printbuf[MAX_READ*2 + 128];
+       char printbuf[MAX_READ*2 + 144];
 };
 
 static const struct init_globals init_data = {
@@ -337,15 +353,16 @@ enum {
        OPTBIT_loglevel, // -l
        OPTBIT_small, // -S
        OPTBIT_timestamp, // -t
-       IF_FEATURE_ROTATE_LOGFILE(OPTBIT_filesize   ,)  // -s
-       IF_FEATURE_ROTATE_LOGFILE(OPTBIT_rotatecnt  ,)  // -b
-       IF_FEATURE_REMOTE_LOG(    OPTBIT_remotelog  ,)  // -R
-       IF_FEATURE_REMOTE_LOG(    OPTBIT_locallog   ,)  // -L
-       IF_FEATURE_IPC_SYSLOG(    OPTBIT_circularlog,)  // -C
-       IF_FEATURE_SYSLOGD_DUP(   OPTBIT_dup        ,)  // -D
-       IF_FEATURE_SYSLOGD_CFG(   OPTBIT_cfg        ,)  // -f
-       IF_FEATURE_KMSG_SYSLOG(   OPTBIT_kmsg       ,)  // -K
-       IF_FEATURE_SYSLOGD_UTC(   OPTBIT_utc        ,)  // -u
+       IF_FEATURE_ROTATE_LOGFILE(    OPTBIT_filesize   ,)      // -s
+       IF_FEATURE_ROTATE_LOGFILE(    OPTBIT_rotatecnt  ,)      // -b
+       IF_FEATURE_REMOTE_LOG(        OPTBIT_remotelog  ,)      // -R
+       IF_FEATURE_REMOTE_LOG(        OPTBIT_locallog   ,)      // -L
+       IF_FEATURE_IPC_SYSLOG(        OPTBIT_circularlog,)      // -C
+       IF_FEATURE_SYSLOGD_DUP(       OPTBIT_dup        ,)      // -D
+       IF_FEATURE_SYSLOGD_CFG(       OPTBIT_cfg        ,)      // -f
+       IF_FEATURE_KMSG_SYSLOG(       OPTBIT_kmsg       ,)      // -K
+       IF_FEATURE_SYSLOGD_UTC(       OPTBIT_utc        ,)      // -u
+       IF_FEATURE_SYSLOGD_ISO8601FMT(OPTBIT_iso8601fmt ,)      // -I
 
        OPT_mark        = 1 << OPTBIT_mark    ,
        OPT_nofork      = 1 << OPTBIT_nofork  ,
@@ -353,38 +370,41 @@ enum {
        OPT_loglevel    = 1 << OPTBIT_loglevel,
        OPT_small       = 1 << OPTBIT_small   ,
        OPT_timestamp   = 1 << OPTBIT_timestamp,
-       OPT_filesize    = IF_FEATURE_ROTATE_LOGFILE((1 << OPTBIT_filesize   )) 
+ 0,
-       OPT_rotatecnt   = IF_FEATURE_ROTATE_LOGFILE((1 << OPTBIT_rotatecnt  )) 
+ 0,
-       OPT_remotelog   = IF_FEATURE_REMOTE_LOG(    (1 << OPTBIT_remotelog  )) 
+ 0,
-       OPT_locallog    = IF_FEATURE_REMOTE_LOG(    (1 << OPTBIT_locallog   )) 
+ 0,
-       OPT_circularlog = IF_FEATURE_IPC_SYSLOG(    (1 << OPTBIT_circularlog)) 
+ 0,
-       OPT_dup         = IF_FEATURE_SYSLOGD_DUP(   (1 << OPTBIT_dup        )) 
+ 0,
-       OPT_cfg         = IF_FEATURE_SYSLOGD_CFG(   (1 << OPTBIT_cfg        )) 
+ 0,
-       OPT_kmsg        = IF_FEATURE_KMSG_SYSLOG(   (1 << OPTBIT_kmsg       )) 
+ 0,
-    OPT_utc         = IF_FEATURE_SYSLOGD_UTC(   (1 << OPTBIT_utc        )) + 0,
+       OPT_filesize    = IF_FEATURE_ROTATE_LOGFILE(    (1 << OPTBIT_filesize   
)) + 0,
+       OPT_rotatecnt   = IF_FEATURE_ROTATE_LOGFILE(    (1 << OPTBIT_rotatecnt  
)) + 0,
+       OPT_remotelog   = IF_FEATURE_REMOTE_LOG(        (1 << OPTBIT_remotelog  
)) + 0,
+       OPT_locallog    = IF_FEATURE_REMOTE_LOG(        (1 << OPTBIT_locallog   
)) + 0,
+       OPT_circularlog = IF_FEATURE_IPC_SYSLOG(        (1 << 
OPTBIT_circularlog)) + 0,
+       OPT_dup         = IF_FEATURE_SYSLOGD_DUP(       (1 << OPTBIT_dup        
)) + 0,
+       OPT_cfg         = IF_FEATURE_SYSLOGD_CFG(       (1 << OPTBIT_cfg        
)) + 0,
+       OPT_kmsg        = IF_FEATURE_KMSG_SYSLOG(       (1 << OPTBIT_kmsg       
)) + 0,
+    OPT_utc         = IF_FEATURE_SYSLOGD_UTC(       (1 << OPTBIT_utc        )) 
+ 0,
+    OPT_iso8601fmt  = IF_FEATURE_SYSLOGD_ISO8601FMT((1 << OPTBIT_iso8601fmt )) 
+ 0,
 };
 #define OPTION_STR "m:nO:l:St" \
-       IF_FEATURE_ROTATE_LOGFILE("s:" ) \
-       IF_FEATURE_ROTATE_LOGFILE("b:" ) \
-       IF_FEATURE_REMOTE_LOG(    "R:*") \
-       IF_FEATURE_REMOTE_LOG(    "L"  ) \
-       IF_FEATURE_IPC_SYSLOG(    "C::") \
-       IF_FEATURE_SYSLOGD_DUP(   "D"  ) \
-       IF_FEATURE_SYSLOGD_CFG(   "f:" ) \
-       IF_FEATURE_KMSG_SYSLOG(   "K"  ) \
-       IF_FEATURE_SYSLOGD_UTC(   "u"  )
+       IF_FEATURE_ROTATE_LOGFILE(    "s:" ) \
+       IF_FEATURE_ROTATE_LOGFILE(    "b:" ) \
+       IF_FEATURE_REMOTE_LOG(        "R:*") \
+       IF_FEATURE_REMOTE_LOG(        "L"  ) \
+       IF_FEATURE_IPC_SYSLOG(        "C::") \
+       IF_FEATURE_SYSLOGD_DUP(       "D"  ) \
+       IF_FEATURE_SYSLOGD_CFG(       "f:" ) \
+       IF_FEATURE_KMSG_SYSLOG(       "K"  ) \
+       IF_FEATURE_SYSLOGD_UTC(       "u"  ) \
+       IF_FEATURE_SYSLOGD_ISO8601FMT("I::")
 #define OPTION_DECL *opt_m, *opt_l \
-       IF_FEATURE_ROTATE_LOGFILE(,*opt_s) \
-       IF_FEATURE_ROTATE_LOGFILE(,*opt_b) \
-       IF_FEATURE_IPC_SYSLOG(    ,*opt_C = NULL) \
-       IF_FEATURE_SYSLOGD_CFG(   ,*opt_f = NULL)
+       IF_FEATURE_ROTATE_LOGFILE(    ,*opt_s) \
+       IF_FEATURE_ROTATE_LOGFILE(    ,*opt_b) \
+       IF_FEATURE_IPC_SYSLOG(        ,*opt_C = NULL) \
+       IF_FEATURE_SYSLOGD_CFG(       ,*opt_f = NULL) \
+       IF_FEATURE_SYSLOGD_ISO8601FMT(,*opt_I = NULL)
 #define OPTION_PARAM &opt_m, &(G.logFile.path), &opt_l \
-       IF_FEATURE_ROTATE_LOGFILE(,&opt_s) \
-       IF_FEATURE_ROTATE_LOGFILE(,&opt_b) \
-       IF_FEATURE_REMOTE_LOG(    ,&remoteAddrList) \
-       IF_FEATURE_IPC_SYSLOG(    ,&opt_C) \
-       IF_FEATURE_SYSLOGD_CFG(   ,&opt_f)
-
+       IF_FEATURE_ROTATE_LOGFILE(    ,&opt_s) \
+       IF_FEATURE_ROTATE_LOGFILE(    ,&opt_b) \
+       IF_FEATURE_REMOTE_LOG(        ,&remoteAddrList) \
+       IF_FEATURE_IPC_SYSLOG(        ,&opt_C) \
+       IF_FEATURE_SYSLOGD_CFG(       ,&opt_f) \
+       IF_FEATURE_SYSLOGD_ISO8601FMT(,&opt_I)
 
 #if ENABLE_FEATURE_SYSLOGD_CFG
 static const CODE* find_by_name(char *name, const CODE* c_set)
@@ -873,6 +893,21 @@ static struct tm * generate_time(struct timeval *tvp, 
struct tm *tmp)
        return tm;
 }
 
+#if ENABLE_FEATURE_SYSLOGD_ISO8601FMT
+static void append_zone_string(char *timestamp, size_t max, const struct tm 
*tmp)
+{
+       if (timestamp && tmp) {
+#if ENABLE_FEATURE_SYSLOGD_UTC
+               if (option_mask32 & OPT_utc)
+               snprintf(timestamp, max, "%c", 'Z');
+           else
+               strftime(timestamp, max, "%z", tmp);
+#else
+               strftime(timestamp, max, "%z", tmp);
+#endif
+       }
+}
+#endif
 
 /* len parameter is used only for "is there a timestamp?" check.
  * NB: some callers cheat and supply len==0 when they know
@@ -887,11 +922,15 @@ static void timestamp_and_log(int pri, char *msg, int len)
                msg[15] == ' ');
        const char *format="%h %e %T";
        char *timestamp = NULL;
-       char timestampbuf[20];
+       char timestampbuf[32];
        /* MMM DD hh:mm:ss default */
        /* 0123456789012345                 - 16 */
        /* MMM DD hh:mm:ss.mmm ENABLE_FEATURE_SYSLOGD_PRECISE_TIMESTAMPS */
        /* 01234567890123456789             - 20 */
+    /* YYYY-MM-DDThh:mm:ss.uuuuuuZ OPT_utc & OPT_iso8601fmt */
+    /* 0123456789012345678901234567     - 28 */
+    /* YYYY-MM-DDThh:mm:ss.uuuuuu+hhmm OPT_iso8601fmt */
+    /* 01234567890123456789012345678901 - 32 */
        struct timeval tvnow;
 #if ENABLE_FEATURE_SYSLOGD_PRECISE_TIMESTAMPS || ENABLE_FEATURE_SYSLOGD_UTC
        struct tm parsed;
@@ -941,6 +980,33 @@ static void timestamp_and_log(int pri, char *msg, int len)
                tmp = generate_time(&tvnow, &tmnow);
        }
 
+#if ENABLE_FEATURE_SYSLOGD_ISO8601FMT
+       if (tmp && !timestamp && G.iso8601fmt >= 0) {
+           format = "%FT%T";
+               /* -I[SPEC]: 0:seconds 1:ms 2:us */
+               n = strftime(timestampbuf + n, sizeof(timestampbuf) - n, 
format, tmp);
+
+           if (G.iso8601fmt == 1 || G.iso8601fmt == 2) {
+               const char *iso8601fracfmt;
+               unsigned long divisor;
+
+               if (G.iso8601fmt == 1) {
+                   iso8601fracfmt = ".%03lu";
+                   divisor = 1000u;
+               } else {
+                   iso8601fracfmt = ".%06lu";
+                   divisor = 1u;
+               }
+
+            n += snprintf(timestampbuf + n, sizeof(timestampbuf) - n, 
iso8601fracfmt, tvnow.tv_usec / divisor);
+        }
+
+        append_zone_string(timestampbuf + n, sizeof(timestampbuf) - n, tmp);
+
+        timestamp = timestampbuf;
+    }
+#endif /* ENABLE_FEATURE_SYSLOGD_ISO8601FMT */
+
 #if ENABLE_FEATURE_SYSLOGD_PRECISE_TIMESTAMPS
        if (tmp && !timestamp) {
                n = strftime(timestampbuf + n, sizeof(timestampbuf) - n, 
format, tmp);
@@ -1138,6 +1204,19 @@ static int NOINLINE syslogd_init(char **argv)
 #if ENABLE_FEATURE_IPC_SYSLOG
        if (opt_C) // -Cn
                G.shm_size = xatoul_range(opt_C, 4, INT_MAX/1024) * 1024;
+#endif
+#if ENABLE_FEATURE_SYSLOGD_ISO8601FMT
+       G.iso8601fmt = -1;
+       if (opts & OPT_iso8601fmt) {
+               G.iso8601fmt = 0; /* default is seconds */
+               if (opt_I) {
+                       static const char iso8601fmts[] ALIGN1 =
+                               "seconds\0""ms\0""us\0";
+                       G.iso8601fmt = index_in_substrings(iso8601fmts, opt_I);
+                       if (G.iso8601fmt < 0)
+                               bb_show_usage();
+               }
+       }
 #endif
        /* If they have not specified remote logging, then log locally */
        if (ENABLE_FEATURE_REMOTE_LOG && !(opts & OPT_remotelog)) // -R
-- 
2.45.0

_______________________________________________
busybox mailing list
busybox@busybox.net
https://lists.busybox.net/mailman/listinfo/busybox

Reply via email to