This is an automated email from the ASF dual-hosted git repository.

xiaoxiang781216 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git

commit 2b274ba0231dc6ae1171239d9875d7c8cfbf78ad
Author: Marco Casaroli <[email protected]>
AuthorDate: Thu Oct 29 16:34:49 2026 +0100

    libs/libc/syslog: Implement openlog() and closelog().
    
    <syslog.h> defined openlog() as a macro that is a block of statements
    and closelog() as an empty macro, and syslog() did not use the ident or
    the options.  Programs that write "(void) openlog(...);" or
    "(void) closelog();" did not compile (tcp-wrappers' tcpd.c), a program
    that declares them, or a link test, did not find them, and the messages
    of a program had no ident.
    
    Make them functions of libc, as in musl: openlog() keeps a copy of the
    ident (up to 31 characters), the options and the facility in the task
    information of the process (task_info_s.ta_openlog, one per task
    group), and the messages of the process get "ident: " before them,
    "ident[pid]: " with LOG_PID.  With LOG_PERROR, syslog() writes the
    message to stderr too.  The other options and the facility have no
    effect: NuttX has no system logger to connect to.  closelog() has no
    descriptor to close; the settings stay, as in musl.
    
    The OS adds the ident in nx_vsyslog(), in the header that it already
    writes, so syslog() needs no buffer and no lock.  nx_vsyslog() now
    writes the header in every configuration, and reads the settings from
    the task information of the running task.  So the messages that the OS
    prints while the process runs (in a system call, for example) get the
    ident too; messages from an interrupt handler have none.  In PROTECTED
    and KERNEL builds the task information is in user memory: the kernel
    reads at most 31 characters of the ident.
    
    Assisted-by: Claude Code:claude-opus-5-5
    Signed-off-by: Marco Casaroli <[email protected]>
---
 drivers/syslog/syslog.h                          | 60 +++++++++++++++++
 drivers/syslog/vsyslog.c                         | 21 ++++--
 drivers/syslog/vsyslog_rfc5424.c                 | 13 ++++
 include/nuttx/tls.h                              | 12 ++++
 include/syslog.h                                 | 14 ++--
 libs/libc/libc.csv                               |  2 +
 libs/libc/syslog/CMakeLists.txt                  |  2 +
 libs/libc/syslog/Make.defs                       |  2 +
 libs/libc/syslog/{lib_syslog.c => lib_openlog.c} | 82 ++++++++++--------------
 libs/libc/syslog/lib_syslog.c                    | 66 +++++++++++++++++++
 10 files changed, 212 insertions(+), 62 deletions(-)

diff --git a/drivers/syslog/syslog.h b/drivers/syslog/syslog.h
index 6b6b7ac616a..2f039e32272 100644
--- a/drivers/syslog/syslog.h
+++ b/drivers/syslog/syslog.h
@@ -30,6 +30,12 @@
 #include <nuttx/config.h>
 
 #include <stdbool.h>
+#include <stdio.h>
+#include <syslog.h>
+
+#include <nuttx/arch.h>
+#include <nuttx/sched.h>
+#include <nuttx/tls.h>
 
 /****************************************************************************
  * Public Data
@@ -53,6 +59,60 @@ const
 #endif
 g_syslog_channel[CONFIG_SYSLOG_MAX_CHANNELS];
 
+/****************************************************************************
+ * Inline Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: syslog_ident
+ *
+ * Description:
+ *   Get the ident that the task group of the caller set with openlog(), and
+ *   write the text after it to 'tail': "[pid]: " with LOG_PID, ": " for a
+ *   non-empty ident, else nothing.  The messages of the OS that run in the
+ *   task get the ident too.  The task information can be in user memory:
+ *   print the ident with a precision of OPENLOG_IDENT_SIZE - 1.  No ident
+ *   in an interrupt handler.
+ *
+ * Returned Value:
+ *   The ident, or "" when there is nothing to print.
+ *
+ ****************************************************************************/
+
+static inline FAR const char *syslog_ident(FAR char *tail, size_t size)
+{
+  FAR struct task_info_s *info;
+  FAR struct tcb_s *tcb;
+
+  tail[0] = '\0';
+  if (up_interrupt_context())
+    {
+      return "";
+    }
+
+  tcb = nxsched_self();
+  if (tcb == NULL || tcb->group == NULL || tcb->group->tg_info == NULL)
+    {
+      return "";
+    }
+
+  info = tcb->group->tg_info;
+  if ((info->ta_openlog.ol_option & LOG_PID) != 0)
+    {
+      snprintf(tail, size, "[%d]: ", tcb->group->tg_pid);
+    }
+  else if (info->ta_openlog.ol_ident[0] != '\0')
+    {
+      snprintf(tail, size, ": ");
+    }
+  else
+    {
+      return "";
+    }
+
+  return info->ta_openlog.ol_ident;
+}
+
 /****************************************************************************
  * Public Function Prototypes
  ****************************************************************************/
diff --git a/drivers/syslog/vsyslog.c b/drivers/syslog/vsyslog.c
index 668d70d8298..a0bccbcfb06 100644
--- a/drivers/syslog/vsyslog.c
+++ b/drivers/syslog/vsyslog.c
@@ -84,7 +84,9 @@ static FAR const char * const g_priority_str[] =
 int nx_vsyslog(int priority, FAR const IPTR char *fmt, FAR va_list *ap)
 {
   struct lib_syslograwstream_s stream;
-  int ret = 0;
+  FAR const char *ident;
+  char tail[16];
+  int ret;
 #ifdef CONFIG_SYSLOG_PROCESS_NAME
   FAR struct tcb_s *tcb = nxsched_self();
 #endif
@@ -147,10 +149,9 @@ int nx_vsyslog(int priority, FAR const IPTR char *fmt, FAR 
va_list *ap)
 #  endif
 #endif
 
-#if defined(CONFIG_SYSLOG_COLOR_OUTPUT) || defined(CONFIG_SYSLOG_TIMESTAMP) || 
\
-    defined(CONFIG_SMP) || defined(CONFIG_SYSLOG_PROCESSID) || \
-    defined(CONFIG_SYSLOG_PRIORITY) || defined(CONFIG_SYSLOG_PREFIX) || \
-    defined(CONFIG_SYSLOG_PROCESS_NAME)
+  /* The ident and the process ID of openlog() */
+
+  ident = syslog_ident(tail, sizeof(tail));
 
   ret = lib_sprintf_internal(&stream.common,
 #if defined(CONFIG_SYSLOG_COLOR_OUTPUT)
@@ -207,6 +208,10 @@ int nx_vsyslog(int priority, FAR const IPTR char *fmt, FAR 
va_list *ap)
 
                              "%s: "
 #endif
+
+  /* Prepend the ident of openlog() */
+
+                             "%.*s%s"
 #ifdef CONFIG_SYSLOG_TIMESTAMP
 #  if defined(CONFIG_SYSLOG_TIMESTAMP_FORMATTED)
 #    if defined(CONFIG_SYSLOG_TIMESTAMP_FORMAT_MICROSECOND)
@@ -258,9 +263,11 @@ int nx_vsyslog(int priority, FAR const IPTR char *fmt, FAR 
va_list *ap)
 
                              , get_task_name(tcb)
 #endif
-                    );
 
-#endif /* CONFIG_SYSLOG_COLOR_OUTPUT || CONFIG_SYSLOG_TIMESTAMP || ... */
+  /* Prepend the ident of openlog() */
+
+                             , OPENLOG_IDENT_SIZE - 1, ident, tail
+                    );
 
   /* Generate the output */
 
diff --git a/drivers/syslog/vsyslog_rfc5424.c b/drivers/syslog/vsyslog_rfc5424.c
index 9a0282874cf..f9f09cc4eb6 100644
--- a/drivers/syslog/vsyslog_rfc5424.c
+++ b/drivers/syslog/vsyslog_rfc5424.c
@@ -105,6 +105,8 @@ int nx_vsyslog(int priority, FAR const IPTR char *fmt, FAR 
va_list *ap)
 #ifdef CONFIG_SYSLOG_RFC5424_HOSTNAME
   char hostname_buf[HOST_NAME_MAX + 1];
 #endif
+  FAR const char *ident;
+  char tail[16];
 
   /* Wrap the low-level output in a stream object and let lib_vsprintf
    * do the work.
@@ -148,6 +150,10 @@ int nx_vsyslog(int priority, FAR const IPTR char *fmt, FAR 
va_list *ap)
     }
 #endif
 
+  /* The ident and the process ID of openlog() start the MSG */
+
+  ident = syslog_ident(tail, sizeof(tail));
+
   /* Output the RFC5424 header */
 
   ret = lib_sprintf_internal(&stream.common,
@@ -190,6 +196,7 @@ int nx_vsyslog(int priority, FAR const IPTR char *fmt, FAR 
va_list *ap)
 #if HAVE_RFC5424_SDATA
       " " /* Space at the end of structured data before message */
 #endif
+      "%.*s%s" /* Ident of openlog() */
 
       /* Beginning of formatted arguments */
 
@@ -214,7 +221,13 @@ int nx_vsyslog(int priority, FAR const IPTR char *fmt, FAR 
va_list *ap)
       , 0 /* TODO: Not sure if synced */
       , 0 /* TODO: Not sure if time zone known */
 #endif
+
+      /* Ident of openlog() */
+
+      , OPENLOG_IDENT_SIZE - 1, ident, tail
+
       /* End of formatted arguments */
+
   );
 
   /* MSG string is generated below from common code for all syslog
diff --git a/include/nuttx/tls.h b/include/nuttx/tls.h
index cc22ff42116..6762c6ac766 100644
--- a/include/nuttx/tls.h
+++ b/include/nuttx/tls.h
@@ -127,6 +127,17 @@ struct usershell_s
 };
 #endif
 
+/* This structure holds the settings of openlog() */
+
+#define OPENLOG_IDENT_SIZE 32
+
+struct openlog_s
+{
+  char ol_ident[OPENLOG_IDENT_SIZE]; /* Prefix of the messages */
+  int  ol_option;                    /* LOG_PID, LOG_PERROR ... */
+  int  ol_facility;                  /* Default facility */
+};
+
 #ifdef CONFIG_PTHREAD_ATFORK
 /* This structure defines the pthread_atfork_s, which is used to manage
  * the funcs that operates on pthread_atfork() method
@@ -164,6 +175,7 @@ struct task_info_s
                                    * libc at the first use
                                    */
 #endif
+  struct openlog_s ta_openlog; /* Settings of openlog() */
 #if CONFIG_LIBC_MAX_EXITFUNS > 0
   struct atexit_list_s ta_exit; /* Exit functions */
 #endif
diff --git a/include/syslog.h b/include/syslog.h
index d394a6474b8..f57a0a79fda 100644
--- a/include/syslog.h
+++ b/include/syslog.h
@@ -65,8 +65,6 @@
 #define LOG_NOWAIT      0x10    /* don't wait for console forks: DEPRECATED */
 #define LOG_PERROR      0x20    /* log to stderr as well */
 
-/* Note: openlog() is not currently supported */
-
 /* The facility argument is used to specify what type of program is logging
  * the message. This lets the configuration file specify that messages from
  * different facilities will be handled differently.
@@ -177,10 +175,13 @@ extern "C"
  *
  *   It is not necessary to call openlog() prior to calling syslog().
  *
+ *   NuttX puts the ident (up to 31 characters) and, with LOG_PID, the
+ *   process ID before each message, and writes the messages to stderr too
+ *   with LOG_PERROR.  It does not use the other options or the facility.
+ *
  ****************************************************************************/
 
-/* Not supported */
-#define openlog(i, o, f) {(void)(i); (void)(o); (void)(f);}
+void openlog(FAR const char *ident, int option, int facility);
 
 /****************************************************************************
  * Name: closelog
@@ -190,10 +191,11 @@ extern "C"
  *   The closelog() function will close any open file descriptors allocated
  *   by previous calls to openlog() or syslog().
  *
+ *   NuttX has no such descriptor.  The settings of openlog() stay.
+ *
  ****************************************************************************/
 
-/* Not supported */
-#define closelog()
+void closelog(void);
 
 /****************************************************************************
  * Name: syslog and vsyslog
diff --git a/libs/libc/libc.csv b/libs/libc/libc.csv
index 73d2ebd5751..3e13e11c85b 100644
--- a/libs/libc/libc.csv
+++ b/libs/libc/libc.csv
@@ -46,6 +46,7 @@
 "clock_getcpuclockid","time.h","","int","pid_t","FAR clockid_t *"
 "clock_getres","time.h","","int","clockid_t","FAR struct timespec *"
 "closedir","dirent.h","","int","DIR *"
+"closelog","syslog.h","","void"
 "crc32","nuttx/crc32.h","","uint32_t","FAR const uint8_t *","size_t"
 "crc32part","nuttx/crc32.h","","uint32_t","FAR const uint8_t 
*","size_t","uint32_t"
 "ctermid","stdio.h","","FAR char *","FAR char *"
@@ -213,6 +214,7 @@
 "ntohq","arpa/inet.h","","uint64_t","uint64_t"
 "ntohs","arpa/inet.h","","uint16_t","uint16_t"
 "opendir","dirent.h","","FAR DIR *","FAR const char *"
+"openlog","syslog.h","","void","FAR const char *","int","int"
 "perror","stdio.h","defined(CONFIG_FILE_STREAM)","void","FAR const char *"
 "pipe","unistd.h","defined(CONFIG_PIPES) && CONFIG_DEV_PIPE_SIZE > 
0","int","int [2]|FAR int *"
 "posix_fallocate","fcntl.h","","int","int","off_t","off_t"
diff --git a/libs/libc/syslog/CMakeLists.txt b/libs/libc/syslog/CMakeLists.txt
index c450efa8338..f9862c40955 100644
--- a/libs/libc/syslog/CMakeLists.txt
+++ b/libs/libc/syslog/CMakeLists.txt
@@ -20,6 +20,8 @@
 #
 # 
##############################################################################
 
+target_sources(c PRIVATE lib_openlog.c)
+
 if(CONFIG_SYSLOG)
   target_sources(c PRIVATE lib_setlogmask.c lib_syslog.c)
 endif()
diff --git a/libs/libc/syslog/Make.defs b/libs/libc/syslog/Make.defs
index e03a4be0da6..866dceaa7c2 100644
--- a/libs/libc/syslog/Make.defs
+++ b/libs/libc/syslog/Make.defs
@@ -22,6 +22,8 @@
 
 # Add the internal C files to the build
 
+CSRCS += lib_openlog.c
+
 ifeq ($(CONFIG_SYSLOG),y)
 CSRCS += lib_syslog.c lib_setlogmask.c
 endif
diff --git a/libs/libc/syslog/lib_syslog.c b/libs/libc/syslog/lib_openlog.c
similarity index 53%
copy from libs/libc/syslog/lib_syslog.c
copy to libs/libc/syslog/lib_openlog.c
index 439ea04ea1f..cdefe5ea4c8 100644
--- a/libs/libc/syslog/lib_syslog.c
+++ b/libs/libc/syslog/lib_openlog.c
@@ -1,5 +1,5 @@
 /****************************************************************************
- * libs/libc/syslog/lib_syslog.c
+ * libs/libc/syslog/lib_openlog.c
  *
  * SPDX-License-Identifier: Apache-2.0
  *
@@ -26,79 +26,63 @@
 
 #include <nuttx/config.h>
 
-#include <stdarg.h>
+#include <string.h>
 #include <syslog.h>
 
-#include <nuttx/syslog/syslog.h>
-
-#include "syslog/syslog.h"
+#include <nuttx/mutex.h>
+#include <nuttx/tls.h>
 
 /****************************************************************************
  * Public Functions
  ****************************************************************************/
 
 /****************************************************************************
- * Name: vsyslog
+ * Name: openlog
  *
  * Description:
- *   The function vsyslog() performs the same task as syslog() with the
- *   difference that it takes a set of arguments which have been obtained
- *   using the stdarg variable argument list macros.
- *
- * Returned Value:
- *   None.
+ *   Set the ident, the options and the default facility of the syslog()
+ *   messages of the process (the task group), as in musl: the OS puts
+ *   "ident: " before each message of the process, "ident[pid]: " with
+ *   LOG_PID, and syslog() writes the message to stderr too with
+ *   LOG_PERROR.  The ident is copied (up to 31 characters).  NuttX does
+ *   not use the other options or the facility.
  *
  ****************************************************************************/
 
-void vsyslog(int priority, FAR const IPTR char *fmt, va_list ap)
+void openlog(FAR const char *ident, int option, int facility)
 {
-  /* Check if this priority is enabled */
+  FAR struct task_info_s *info = task_get_info();
+  FAR struct openlog_s *state;
+  size_t n = 0;
 
-  if ((g_syslog_mask & LOG_MASK(LOG_PRI(priority))) != 0)
+  if (info == NULL)
     {
-      /* Yes.. Perform the nx_vsyslog system call.
-       *
-       * NOTE:  The va_list parameter is passed by reference.  That is
-       * because the va_list is a structure in some compilers and passing
-       * of structures in the NuttX syscalls does not work.
-       */
-
-#ifdef va_copy
-      va_list copy;
+      return;
+    }
 
-      va_copy(copy, ap);
-      nx_vsyslog(priority, fmt, &copy);
-      va_end(copy);
-#else
-      nx_vsyslog(priority, fmt, &ap);
-#endif
+  nxrmutex_lock(&info->ta_lock);
+  state = &info->ta_openlog;
+  if (ident != NULL)
+    {
+      n = strnlen(ident, sizeof(state->ol_ident) - 1);
+      memcpy(state->ol_ident, ident, n);
     }
+
+  state->ol_ident[n] = '\0';
+  state->ol_option   = option;
+  state->ol_facility = facility;
+  nxrmutex_unlock(&info->ta_lock);
 }
 
 /****************************************************************************
- * Name: syslog
+ * Name: closelog
  *
  * Description:
- *   syslog() generates a log message. The priority argument is formed by
- *   ORing the facility and the level values (see include/syslog.h). The
- *   remaining arguments are a format, as in printf and any arguments to the
- *   format.
- *
- *   The NuttX implementation does not support any special formatting
- *   characters beyond those supported by printf.
- *
- * Returned Value:
- *   None.
+ *   Close the descriptors that openlog() or syslog() opened.  NuttX opens
+ *   none.  As in musl, the settings of openlog() stay.
  *
  ****************************************************************************/
 
-void syslog(int priority, FAR const IPTR char *fmt, ...)
+void closelog(void)
 {
-  va_list ap;
-
-  /* Let vsyslog do the work */
-
-  va_start(ap, fmt);
-  vsyslog(priority, fmt, ap);
-  va_end(ap);
 }
diff --git a/libs/libc/syslog/lib_syslog.c b/libs/libc/syslog/lib_syslog.c
index 439ea04ea1f..1d144dba478 100644
--- a/libs/libc/syslog/lib_syslog.c
+++ b/libs/libc/syslog/lib_syslog.c
@@ -27,12 +27,74 @@
 #include <nuttx/config.h>
 
 #include <stdarg.h>
+#include <stdio.h>
 #include <syslog.h>
+#include <unistd.h>
 
 #include <nuttx/syslog/syslog.h>
+#include <nuttx/tls.h>
 
 #include "syslog/syslog.h"
 
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+#ifndef __KERNEL__
+/****************************************************************************
+ * Name: vsyslog_perror
+ *
+ * Description:
+ *   With LOG_PERROR of openlog(), write the message to stderr too, with the
+ *   ident and the process ID before it and a newline after it.
+ *
+ ****************************************************************************/
+
+static void vsyslog_perror(FAR const IPTR char *fmt, va_list ap)
+{
+  FAR struct task_info_s *info = task_get_info();
+  FAR const IPTR char *end;
+  int option;
+
+  if (info == NULL
+#ifdef CONFIG_BUILD_FLAT
+      || up_interrupt_context()
+#endif
+     )
+    {
+      return;
+    }
+
+  option = info->ta_openlog.ol_option;
+  if ((option & LOG_PERROR) == 0)
+    {
+      return;
+    }
+
+  if ((option & LOG_PID) != 0)
+    {
+      dprintf(STDERR_FILENO, "%.*s[%d]: ", OPENLOG_IDENT_SIZE - 1,
+              info->ta_openlog.ol_ident, getpid());
+    }
+  else if (info->ta_openlog.ol_ident[0] != '\0')
+    {
+      dprintf(STDERR_FILENO, "%.*s: ", OPENLOG_IDENT_SIZE - 1,
+              info->ta_openlog.ol_ident);
+    }
+
+  vdprintf(STDERR_FILENO, fmt, ap);
+
+  for (end = fmt; *end != '\0'; end++)
+    {
+    }
+
+  if (end == fmt || *(end - 1) != '\n')
+    {
+      write(STDERR_FILENO, "\n", 1);
+    }
+}
+#endif
+
 /****************************************************************************
  * Public Functions
  ****************************************************************************/
@@ -72,6 +134,10 @@ void vsyslog(int priority, FAR const IPTR char *fmt, 
va_list ap)
 #else
       nx_vsyslog(priority, fmt, &ap);
 #endif
+
+#ifndef __KERNEL__
+      vsyslog_perror(fmt, ap);
+#endif
     }
 }
 

Reply via email to