[PATCH v4 1/1] syslogd: Add a configurable option to log timestamps in UTC.

Grant Erickson gerickson at nuovations.com
Fri Apr 4 16:36:41 UTC 2025


This adds a configurable option 'FEATURE_SYSLOGD_UTC' enabling a
command line option ('-u') that directs syslogd to log timestamps in
Coordinated Universal Time (UTC) rather than in local time.

Signed-off-by: Grant Erickson <gerickson at nuovations.com>
---
 sysklogd/syslogd.c | 61 +++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 58 insertions(+), 3 deletions(-)

diff --git a/sysklogd/syslogd.c b/sysklogd/syslogd.c
index 7558051f0e7f..8103611143a1 100644
--- a/sysklogd/syslogd.c
+++ b/sysklogd/syslogd.c
@@ -35,6 +35,15 @@
 //config:	This enables syslogd to rotate the message files
 //config:	on his own. No need to use an external rotate script.
 //config:
+//config:config FEATURE_SYSLOGD_UTC
+//config:	bool "Optionally log timestamps in UTC"
+//config:	default n
+//config:	depends on SYSLOGD
+//config:	help
+//config:	This enables a command line option ('-u') that directs
+//config:	syslogd to log timestamps in Coordinated Universal Time
+//config:	(UTC) rather than in local time.
+//config:
 //config:config FEATURE_REMOTE_LOG
 //config:	bool "Remote Log support"
 //config:	default y
@@ -147,6 +156,9 @@
 //usage:	)
 //usage:     "\n	-l N		Log only messages more urgent than prio N (1-8)"
 //usage:     "\n	-S		Smaller output"
+//usage:	IF_FEATURE_SYSLOGD_UTC(
+//usage:     "\n	-u		Log timestamps in Coordinated Universal Time (UTC)"
+//usage:	)
 //usage:     "\n	-t		Strip client-generated timestamps"
 //usage:	IF_FEATURE_SYSLOGD_DUP(
 //usage:     "\n	-D		Drop duplicates"
@@ -333,6 +345,7 @@ enum {
 	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
 
 	OPT_mark        = 1 << OPTBIT_mark    ,
 	OPT_nofork      = 1 << OPTBIT_nofork  ,
@@ -348,6 +361,7 @@ enum {
 	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,
 };
 #define OPTION_STR "m:nO:l:St" \
 	IF_FEATURE_ROTATE_LOGFILE("s:" ) \
@@ -357,7 +371,8 @@ enum {
 	IF_FEATURE_IPC_SYSLOG(    "C::") \
 	IF_FEATURE_SYSLOGD_DUP(   "D"  ) \
 	IF_FEATURE_SYSLOGD_CFG(   "f:" ) \
-	IF_FEATURE_KMSG_SYSLOG(   "K"  )
+	IF_FEATURE_KMSG_SYSLOG(   "K"  ) \
+	IF_FEATURE_SYSLOGD_UTC(   "u"  )
 #define OPTION_DECL *opt_m, *opt_l \
 	IF_FEATURE_ROTATE_LOGFILE(,*opt_s) \
 	IF_FEATURE_ROTATE_LOGFILE(,*opt_b) \
@@ -818,6 +833,25 @@ static void parse_fac_prio_20(int pri, char *res20)
 	snprintf(res20, 20, "<%d>", pri);
 }
 
+static char *timestamp_from_time(const time_t *time)
+{
+	char *timestamp = NULL;
+
+	if (time) {
+#if ENABLE_FEATURE_SYSLOGD_UTC
+		if (option_mask32 & OPT_utc)
+			timestamp = asctime(gmtime(time));
+		else
+			timestamp = asctime(localtime(time));
+#else
+		timestamp = ctime(time);
+#endif
+		timestamp += 4; /* skip day of week */
+	}
+
+	return timestamp;
+}
+
 /* len parameter is used only for "is there a timestamp?" check.
  * NB: some callers cheat and supply len==0 when they know
  * that there is no timestamp, short-circuiting the test. */
@@ -833,8 +867,29 @@ static void timestamp_and_log(int pri, char *msg, int len)
 	) {
 		if (!(option_mask32 & OPT_timestamp)) {
 			/* use message timestamp */
+#if ENABLE_FEATURE_SYSLOGD_UTC
+			if (option_mask32 & OPT_utc) {
+				struct tm parsed, local;
+				now = time(NULL);
+				localtime_r(&now, &local);
+				if (strptime(msg, "%h %e %T", &parsed) != NULL) {
+					parsed.tm_gmtoff	= local.tm_gmtoff;
+					parsed.tm_zone		= local.tm_zone;
+					parsed.tm_year		= local.tm_year;
+					parsed.tm_isdst		= local.tm_isdst;
+					now = mktime(&parsed);
+					timestamp = asctime(gmtime(&now)) + 4;
+				} else {
+					timestamp = msg;
+				}
+			} else {
+				timestamp = msg;
+				now = 0;
+			}
+#else
 			timestamp = msg;
 			now = 0;
+#endif
 		}
 		msg += 16;
 	}
@@ -844,7 +899,7 @@ static void timestamp_and_log(int pri, char *msg, int len)
 		struct timeval tv;
 		xgettimeofday(&tv);
 		now = tv.tv_sec;
-		timestamp = ctime(&now) + 4; /* skip day of week */
+		timestamp = timestamp_from_time(&now);
 		/* overwrite year by milliseconds, zero terminate */
 		sprintf(timestamp + 15, ".%03u", (unsigned)tv.tv_usec / 1000u);
 	} else {
@@ -853,7 +908,7 @@ static void timestamp_and_log(int pri, char *msg, int len)
 #else
 	if (!timestamp) {
 		time(&now);
-		timestamp = ctime(&now) + 4; /* skip day of week */
+		timestamp = timestamp_from_time(&now);
 	}
 	timestamp[15] = '\0';
 #endif
-- 
2.45.0



More information about the busybox mailing list