[Bug 268436] [libc] syslog() and vsyslog() do not preserve the errno at the time of the call.

From: <bugzilla-noreply_at_freebsd.org>
Date: Sun, 01 Sep 2024 08:56:53 UTC
https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=268436

--- Comment #4 from Hodong <hodong@nimfsoft.art> ---
#include <syslog.h>
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>

void* c_realloc (void* ptr, size_t size)
{
  if (!size)
  {
    free (ptr);
    return NULL;
  }

  void* mem = realloc (ptr, size);

  if (mem)
    return mem;

  perror (__PRETTY_FUNCTION__);
  abort ();
}

char* c_str_join (const char *str, ...)
{
  va_list ap;
  size_t  offset = 0;
  char*   result = NULL;

  va_start (ap, str);

  for (const char* s = str; s != NULL; s = va_arg (ap, const char*))
  {
    size_t len = strlen (s);
    result = c_realloc (result, offset + len + 1);
    memcpy (result + offset, s, len);
    offset = offset + len;
  }

  va_end (ap);

  if (result)
    result[offset] = '\0';

  return result;
}

void c_log (int priority, const char* format, ...)
{
  const char* prefix;
  char*       new_format;
  va_list     args;

  switch (priority)
  {
    case LOG_EMERG:
      prefix = "EMERGENCY";
      break;
    case LOG_ALERT:
      prefix = "ALERT";
      break;
    case LOG_CRIT:
      prefix = "CRITICAL";
      break;
    case LOG_ERR:
      prefix = "ERROR";
      break;
    case LOG_WARNING:
      prefix = "WARNING";
      break;
    case LOG_NOTICE:
      prefix = "NOTICE";
      break;
    case LOG_INFO:
      prefix = "INFO";
      break;
    case LOG_DEBUG:
      prefix = "DEBUG";
      break;
    default:
      prefix = "NOTICE";
      break;
  }

  openlog (getprogname(), LOG_PID | LOG_PERROR, LOG_DAEMON);
  new_format = c_str_join (prefix, ": ", format, NULL);

  /*
   * 2022.12.18
   * https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=268436
   * The freebsd libc syslog, vsyslog does not preserve the errno at the time
of
   * the call, so errno may change after the syslog call.
   */
  //int saved_errno = errno;
  va_start (args, format);
  vsyslog  (priority, new_format, args);
  va_end   (args);
  //errno = saved_errno;

  free (new_format);
  closelog ();
}

#define c_log_critical(format, ...) \
  c_log (LOG_CRIT, __FILE__ ":%d:%s: " format, \
         __LINE__, __PRETTY_FUNCTION__, ## __VA_ARGS__)

#define c_log_warning(format, ...) \
  c_log (LOG_WARNING, __FILE__ ":%d:%s: " format, \
         __LINE__, __PRETTY_FUNCTION__, ## __VA_ARGS__)

#define c_log_info(format, ...) \
  c_log (LOG_INFO, format, ## __VA_ARGS__)

int main ()
{
  printf ("before: %d\n", errno);
  c_log_info ("Example: %d", errno);
  c_log_warning ("Example: %d", errno);
  c_log_critical ("Example: %d", errno);
  printf ("after: %d\n", errno);
  return 0;
}

When I tested this code in the past, there was an issue where errno was changed
after calling vsyslog().
So I used this:

  int saved_errno = errno;
  va_start (args, format);
  vsyslog  (priority, new_format, args);
  va_end   (args);
  errno = saved_errno;

But now that I've tested it again, errno doesn't change after calling
vsyslog().

  //int saved_errno = errno;
  va_start (args, format);
  vsyslog  (priority, new_format, args);
  va_end   (args);
  //errno = saved_errno;

So this issue seems to be resolved and I think we can close this issue.

-- 
You are receiving this mail because:
You are the assignee for the bug.