Skip to content

Conversation

alejandro-colomar
Copy link
Collaborator

@alejandro-colomar alejandro-colomar commented Jul 13, 2025

This allows compacting a lot of code. It also makes it easier to discern lines that print to actual files, from those that print to stderr/stdout.


Revisions:

v2
$ git range-diff f6e676334455^..gh/eprintf shadow/master..eprintf 
1:  f6e67633 ! 1:  302aae32 lib/io/fprintf/: eprintf(): Add function to print to stderr
    @@ lib/io/fprintf/eprintf.c (new)
     +// SPDX-License-Identifier: BSD-3-Clause
     +
     +
    -+#include <config.h>
    ++#include "config.h"
     +
     +#include "io/fprintf/eprintf.h"
     +
    @@ lib/io/fprintf/eprintf.h (new)
     +#define SHADOW_INCLUDE_LIB_IO_FPRINTF_EPRINTF_H_
     +
     +
    -+#include <config.h>
    ++#include "config.h"
     +
     +#include <stdarg.h>
     +#include <stdio.h>
2:  1c1568e1 = 2:  a3ed1da0 lib/, src/: Use eprintf() instead of its pattern
3:  be83d1b4 < -:  -------- src/vipw.c: usage(): Print everything to the same stream
4:  c3af808a < -:  -------- lib/, src/: Use printf(3) instead of its pattern
v2b
  • Rebase
$ git rd 
1:  302aae32 = 1:  da4c7959 lib/io/fprintf/: eprintf(): Add function to print to stderr
2:  a3ed1da0 ! 2:  13a80305 lib/, src/: Use eprintf() instead of its pattern
    @@ src/login.c: int main (int argc, char **argv)
                exit (0);
        } else if (child != 0) {
     @@ src/login.c: int main (int argc, char **argv)
    -   if (getppid() == 1) {
    +   if (1 == initial_pid) {
                setsid();
                if (ioctl(0, TIOCSCTTY, 1) != 0) {
     -                  fprintf (stderr, _("TIOCSCTTY failed on %s"), tty);
v3
  • Add and use strerrno(). This compacts some lines further.
$ git rd
1:  da4c7959 = 1:  da4c7959 lib/io/fprintf/: eprintf(): Add function to print to stderr
2:  13a80305 = 2:  13a80305 lib/, src/: Use eprintf() instead of its pattern
-:  -------- > 3:  e1cddf24 lib/string/: strerrno(): Add function
-:  -------- > 4:  767c2377 lib/, src/: Use strerrno() instead of its pattern
v4
  • Fix definition of SYSLOG() to remove the weird double parentheses.
  • Fix non-matching parentheses in SYSLOG() call.
$ git rd 
1:  da4c7959 = 1:  da4c7959 lib/io/fprintf/: eprintf(): Add function to print to stderr
2:  13a80305 = 2:  13a80305 lib/, src/: Use eprintf() instead of its pattern
3:  e1cddf24 = 3:  e1cddf24 lib/string/: strerrno(): Add function
4:  767c2377 = 4:  767c2377 lib/, src/: Use strerrno() instead of its pattern
-:  -------- > 5:  7e6bef2e src/su.c: Fix incorrect (non-matching) parentheses
-:  -------- > 6:  a9900489 lib/defines.h, lib/, src/: Redefine SYSLOG() as a variadic macro
v5
  • Add moar wrappers, fix moar bugs, make code moar readable.
$ git rd 
 1:  da4c7959 =  1:  da4c7959 lib/io/fprintf/: eprintf(): Add function to print to stderr
 2:  13a80305 =  2:  13a80305 lib/, src/: Use eprintf() instead of its pattern
 3:  e1cddf24 =  3:  e1cddf24 lib/string/: strerrno(): Add function
 4:  767c2377 =  4:  767c2377 lib/, src/: Use strerrno() instead of its pattern
 5:  7e6bef2e =  5:  7e6bef2e src/su.c: Fix incorrect (non-matching) parentheses
 6:  a9900489 =  6:  a9900489 lib/defines.h, lib/, src/: Redefine SYSLOG() as a variadic macro
 -:  -------- >  7:  ca6382ba lib/: Move <syslog.h> wrappers to "io/syslog.h"
 -:  -------- >  8:  eb3b2517 lib/io/: syslog_c(): Implement SYSLOG() with a helper function
 -:  -------- >  9:  82cf1bd0 lib/io/syslog.h: Call setlocale(3) and free(3) unconditionally
 -:  -------- > 10:  67826ff5 lib/io/fprintf/: [v]fprinte(): Add function
 -:  -------- > 11:  53eaccf5 lib/io/fprintf/: [v]eprinte(): Add function
 -:  -------- > 12:  a7e0a585 lib/, src/: Use eprinte() instead of its pattern
 -:  -------- > 13:  ec4bcad1 lib/: Use [v]fprinte() instead of its pattern
 -:  -------- > 14:  15c8269f lib/io/syslog.h: SYSLOGE(): Add macro
 -:  -------- > 15:  73f63bd4 src/userdel.c: Fix error message
 -:  -------- > 16:  2c45897a lib/, src/: Use SYSLOGE() instead of its pattern
v5b
  • tfix
$ git rd 
 1:  da4c7959 =  1:  da4c7959 lib/io/fprintf/: eprintf(): Add function to print to stderr
 2:  13a80305 =  2:  13a80305 lib/, src/: Use eprintf() instead of its pattern
 3:  e1cddf24 =  3:  e1cddf24 lib/string/: strerrno(): Add function
 4:  767c2377 =  4:  767c2377 lib/, src/: Use strerrno() instead of its pattern
 5:  7e6bef2e =  5:  7e6bef2e src/su.c: Fix incorrect (non-matching) parentheses
 6:  a9900489 =  6:  a9900489 lib/defines.h, lib/, src/: Redefine SYSLOG() as a variadic macro
 7:  ca6382ba =  7:  ca6382ba lib/: Move <syslog.h> wrappers to "io/syslog.h"
 8:  eb3b2517 =  8:  eb3b2517 lib/io/: syslog_c(): Implement SYSLOG() with a helper function
 9:  82cf1bd0 =  9:  82cf1bd0 lib/io/syslog.h: Call setlocale(3) and free(3) unconditionally
10:  67826ff5 ! 10:  9ad98eef lib/io/fprintf/: [v]fprinte(): Add function
    @@ lib/io/fprintf/fprinte.h (new)
     +#include "attr.h"
     +
     +
    -+format_attr(printf, 2, 2)
    ++format_attr(printf, 2, 3)
     +inline int fprinte(FILE *restrict stream, const char *restrict fmt, ...);
     +format_attr(printf, 2, 0)
     +inline int vfprinte(FILE *restrict stream, const char *restrict fmt, va_list ap);
11:  53eaccf5 = 11:  ff79b1d7 lib/io/fprintf/: [v]eprinte(): Add function
12:  a7e0a585 = 12:  79ce27b7 lib/, src/: Use eprinte() instead of its pattern
13:  ec4bcad1 = 13:  adf040bd lib/: Use [v]fprinte() instead of its pattern
14:  15c8269f = 14:  3c56b00e lib/io/syslog.h: SYSLOGE(): Add macro
15:  73f63bd4 = 15:  215bfe62 src/userdel.c: Fix error message
16:  2c45897a = 16:  2e8be431 lib/, src/: Use SYSLOGE() instead of its pattern
v6
  • SYSLOG_C() must be a macro. It does some interesting magic!
$ git rd 
 1:  da4c7959 =  1:  da4c7959 lib/io/fprintf/: eprintf(): Add function to print to stderr
 2:  13a80305 =  2:  13a80305 lib/, src/: Use eprintf() instead of its pattern
 3:  e1cddf24 =  3:  e1cddf24 lib/string/: strerrno(): Add function
 4:  767c2377 =  4:  767c2377 lib/, src/: Use strerrno() instead of its pattern
 5:  7e6bef2e =  5:  7e6bef2e src/su.c: Fix incorrect (non-matching) parentheses
 6:  a9900489 =  6:  a9900489 lib/defines.h, lib/, src/: Redefine SYSLOG() as a variadic macro
 7:  ca6382ba =  7:  ca6382ba lib/: Move <syslog.h> wrappers to "io/syslog.h"
 8:  eb3b2517 !  8:  d9cb90ca lib/io/: syslog_c(): Implement SYSLOG() with a helper function
    @@ Metadata
     Author: Alejandro Colomar <[email protected]>
     
      ## Commit message ##
    -    lib/io/: syslog_c(): Implement SYSLOG() with a helper function
    +    lib/io/syslog.h: SYSLOG_C(): Split code to helper macro
    +
    +    The name of this macro makes it more evident what it does.  It's a
    +    C-locale version of syslog(3).  We need to implement it as a macro
    +    so that arguments such as strerror(3) are evaluated after setting
    +    the C locale.  This would be impossible with a function.
     
         Signed-off-by: Alejandro Colomar <[email protected]>
     
    - ## lib/io/syslog.c ##
    -@@
    - #include "config.h"
    - 
    - #include "io/syslog.h"
    -+
    -+#include <stdarg.h>
    -+
    -+
    -+extern inline void syslog_c(int priority, const char *restrict fmt, ...);
    -+extern inline void vsyslog_c(int priority, const char *restrict fmt, va_list ap);
    -
      ## lib/io/syslog.h ##
    -@@
    - #include "config.h"
    - 
    - #include <locale.h>
    -+#include <stdarg.h>
    - #include <stddef.h>
    - #include <stdlib.h>
    - #include <string.h>
     @@
      #define LOG_AUTHPRIV LOG_AUTH
      #endif
    @@ lib/io/syslog.h
     -          }                                                       \
     -  } while (false)
     -#else                             /* !ENABLE_NLS */
    -+#define SYSLOG(...)  syslog_c(__VA_ARGS__)
    ++#define SYSLOG(...)  SYSLOG_C(__VA_ARGS__)
     +#else
      #define SYSLOG(...)  syslog(__VA_ARGS__)
     -#endif                            /* !ENABLE_NLS */
    @@ lib/io/syslog.h
      #define OPENLOG(progname) openlog(progname, SYSLOG_OPTIONS, SYSLOG_FACILITY)
      
      
    -+inline void syslog_c(int priority, const char *restrict fmt, ...);
    -+inline void vsyslog_c(int priority, const char *restrict fmt, va_list ap);
    -+
    -+
     +// system log C-locale
    -+inline void
    -+syslog_c(int priority, const char *restrict fmt, ...)
    -+{
    -+  va_list  ap;
    -+
    -+  va_start(ap, fmt);
    -+  vsyslog_c(priority, fmt, ap);
    -+  va_end(ap);
    -+}
    -+
    -+
    -+// va_list system log C-locale
    -+inline void
    -+vsyslog_c(int priority, const char *restrict fmt, va_list ap)
    -+{
    -+  char *old_locale;
    -+  char *saved_locale;
    -+
    -+  old_locale = setlocale(LC_ALL, NULL);
    -+  saved_locale = NULL;
    -+
    -+  if (NULL != old_locale)
    -+          saved_locale = strdup(old_locale);
    -+
    -+  if (NULL != saved_locale)
    -+          setlocale(LC_ALL, "C");
    -+
    -+  vsyslog(priority, fmt, ap);
    -+
    -+  if (NULL != saved_locale) {
    -+          setlocale(LC_ALL, saved_locale);
    -+          free(saved_locale);
    -+  }
    -+}
    ++#define SYSLOG_C(...)  do                                             \
    ++{                                                                     \
    ++  char  *old_locale;                                            \
    ++  char  *saved_locale;                                          \
    ++                                                                      \
    ++  old_locale = setlocale(LC_ALL, NULL);                         \
    ++  saved_locale = NULL;                                          \
    ++                                                                      \
    ++  if (NULL != old_locale)                                       \
    ++          saved_locale = strdup(old_locale);                    \
    ++                                                                      \
    ++  if (NULL != saved_locale) {                                   \
    ++          setlocale(LC_ALL, "C");                               \
    ++                                                                      \
    ++  syslog(__VA_ARGS__);                                          \
    ++  if (NULL != saved_locale) {                                   \
    ++          setlocale(LC_ALL, saved_locale);                      \
    ++          free(saved_locale);                                   \
    ++  }                                                             \
    ++} while (0)
     +
     +
      #endif  // include guard
 9:  82cf1bd0 <  -:  -------- lib/io/syslog.h: Call setlocale(3) and free(3) unconditionally
 -:  -------- >  9:  1f0531b1 lib/io/syslog.h: Rename local variable
 -:  -------- > 10:  41bd7c81 lib/io/syslog.h: SYSLOG_C(): Use a single local variable
 -:  -------- > 11:  163ebeea lib/io/syslog.h: SYSLOG_C(): Call setlocale(3) and free(3) unconditionally
10:  9ad98eef = 12:  95463ee9 lib/io/fprintf/: [v]fprinte(): Add function
11:  ff79b1d7 = 13:  1c37648a lib/io/fprintf/: [v]eprinte(): Add function
12:  79ce27b7 = 14:  d45e1fee lib/, src/: Use eprinte() instead of its pattern
13:  adf040bd = 15:  cfecd5ca lib/: Use [v]fprinte() instead of its pattern
14:  3c56b00e ! 16:  3caa45d7 lib/io/syslog.h: SYSLOGE(): Add macro
    @@ lib/io/syslog.h
     +)
     +
     +
    - inline void syslog_c(int priority, const char *restrict fmt, ...);
    - inline void vsyslog_c(int priority, const char *restrict fmt, va_list ap);
    - 
    + // system log C-locale
    + #define SYSLOG_C(...)  do                                             \
    + {                                                                     \
15:  215bfe62 = 17:  eaed086d src/userdel.c: Fix error message
16:  2e8be431 = 18:  5b44ec25 lib/, src/: Use SYSLOGE() instead of its pattern
v6b
  • fix braces
$ git rd 
 1:  da4c7959 =  1:  da4c7959 lib/io/fprintf/: eprintf(): Add function to print to stderr
 2:  13a80305 =  2:  13a80305 lib/, src/: Use eprintf() instead of its pattern
 3:  e1cddf24 =  3:  e1cddf24 lib/string/: strerrno(): Add function
 4:  767c2377 =  4:  767c2377 lib/, src/: Use strerrno() instead of its pattern
 5:  7e6bef2e =  5:  7e6bef2e src/su.c: Fix incorrect (non-matching) parentheses
 6:  a9900489 =  6:  a9900489 lib/defines.h, lib/, src/: Redefine SYSLOG() as a variadic macro
 7:  ca6382ba =  7:  ca6382ba lib/: Move <syslog.h> wrappers to "io/syslog.h"
 8:  d9cb90ca !  8:  73336b3f lib/io/syslog.h: SYSLOG_C(): Split code to helper macro
    @@ lib/io/syslog.h
     +  if (NULL != old_locale)                                       \
     +          saved_locale = strdup(old_locale);                    \
     +                                                                      \
    -+  if (NULL != saved_locale) {                                   \
    ++  if (NULL != saved_locale)                                     \
     +          setlocale(LC_ALL, "C");                               \
     +                                                                      \
     +  syslog(__VA_ARGS__);                                          \
 9:  1f0531b1 !  9:  063966cc lib/io/syslog.h: Rename local variable
    @@ lib/io/syslog.h
     +  if (NULL != l_)                                               \
     +          saved_locale = strdup(l_);                            \
                                                                            \
    -   if (NULL != saved_locale) {                                   \
    +   if (NULL != saved_locale)                                     \
                setlocale(LC_ALL, "C");                               \
10:  41bd7c81 ! 10:  ab24ab95 lib/io/syslog.h: SYSLOG_C(): Use a single local variable
    @@ lib/io/syslog.h
     -          saved_locale = strdup(l_);                            \
     +          l_ = strdup(l_);                                      \
                                                                            \
    --  if (NULL != saved_locale) {                                   \
    -+  if (NULL != l_) {                                             \
    +-  if (NULL != saved_locale)                                     \
    ++  if (NULL != l_)                                               \
                setlocale(LC_ALL, "C");                               \
                                                                            \
        syslog(__VA_ARGS__);                                          \
11:  163ebeea = 11:  07f77ecf lib/io/syslog.h: SYSLOG_C(): Call setlocale(3) and free(3) unconditionally
12:  95463ee9 = 12:  4d3b887d lib/io/fprintf/: [v]fprinte(): Add function
13:  1c37648a = 13:  e2e2c4fd lib/io/fprintf/: [v]eprinte(): Add function
14:  d45e1fee = 14:  058f311a lib/, src/: Use eprinte() instead of its pattern
15:  cfecd5ca = 15:  3b1c3231 lib/: Use [v]fprinte() instead of its pattern
16:  3caa45d7 = 16:  955ab8bf lib/io/syslog.h: SYSLOGE(): Add macro
17:  eaed086d = 17:  7be1c698 src/userdel.c: Fix error message
18:  5b44ec25 = 18:  2e1ee543 lib/, src/: Use SYSLOGE() instead of its pattern
v6c
  • Use do-while(0) to implement SYSLOGE()
$ git rd 
 1:  da4c7959 =  1:  da4c7959 lib/io/fprintf/: eprintf(): Add function to print to stderr
 2:  13a80305 =  2:  13a80305 lib/, src/: Use eprintf() instead of its pattern
 3:  e1cddf24 =  3:  e1cddf24 lib/string/: strerrno(): Add function
 4:  767c2377 =  4:  767c2377 lib/, src/: Use strerrno() instead of its pattern
 5:  7e6bef2e =  5:  7e6bef2e src/su.c: Fix incorrect (non-matching) parentheses
 6:  a9900489 =  6:  a9900489 lib/defines.h, lib/, src/: Redefine SYSLOG() as a variadic macro
 7:  ca6382ba =  7:  ca6382ba lib/: Move <syslog.h> wrappers to "io/syslog.h"
 8:  73336b3f =  8:  73336b3f lib/io/syslog.h: SYSLOG_C(): Split code to helper macro
 9:  063966cc =  9:  063966cc lib/io/syslog.h: Rename local variable
10:  ab24ab95 = 10:  ab24ab95 lib/io/syslog.h: SYSLOG_C(): Use a single local variable
11:  07f77ecf = 11:  07f77ecf lib/io/syslog.h: SYSLOG_C(): Call setlocale(3) and free(3) unconditionally
12:  4d3b887d = 12:  4d3b887d lib/io/fprintf/: [v]fprinte(): Add function
13:  e2e2c4fd = 13:  e2e2c4fd lib/io/fprintf/: [v]eprinte(): Add function
14:  058f311a = 14:  058f311a lib/, src/: Use eprinte() instead of its pattern
15:  3b1c3231 = 15:  3b1c3231 lib/: Use [v]fprinte() instead of its pattern
16:  955ab8bf ! 16:  47cf544a lib/io/syslog.h: SYSLOGE(): Add macro
    @@ lib/io/syslog.h
      
      
     +// system log errno
    -+#define SYSLOGE(prio, fmt, ...)                                       \
    -+(                                                                     \
    ++#define SYSLOGE(prio, fmt, ...)  do                                   \
    ++{                                                                     \
     +  SYSLOG(prio, "" fmt ": %s" __VA_OPT__(,) __VA_ARGS__, strerrno()) \
    -+)
    ++} while (0)
     +
     +
      // system log C-locale
17:  7be1c698 = 17:  9faad6e1 src/userdel.c: Fix error message
18:  2e1ee543 = 18:  e0290fcb lib/, src/: Use SYSLOGE() instead of its pattern
v6d
  • Fix semicolons.
$ git rd
 1:  da4c7959 =  1:  da4c7959 lib/io/fprintf/: eprintf(): Add function to print to stderr
 2:  13a80305 =  2:  13a80305 lib/, src/: Use eprintf() instead of its pattern
 3:  e1cddf24 =  3:  e1cddf24 lib/string/: strerrno(): Add function
 4:  767c2377 =  4:  767c2377 lib/, src/: Use strerrno() instead of its pattern
 5:  7e6bef2e =  5:  7e6bef2e src/su.c: Fix incorrect (non-matching) parentheses
 6:  a9900489 =  6:  a9900489 lib/defines.h, lib/, src/: Redefine SYSLOG() as a variadic macro
 7:  ca6382ba =  7:  ca6382ba lib/: Move <syslog.h> wrappers to "io/syslog.h"
 8:  73336b3f =  8:  73336b3f lib/io/syslog.h: SYSLOG_C(): Split code to helper macro
 9:  063966cc =  9:  063966cc lib/io/syslog.h: Rename local variable
10:  ab24ab95 = 10:  ab24ab95 lib/io/syslog.h: SYSLOG_C(): Use a single local variable
11:  07f77ecf = 11:  07f77ecf lib/io/syslog.h: SYSLOG_C(): Call setlocale(3) and free(3) unconditionally
12:  4d3b887d = 12:  4d3b887d lib/io/fprintf/: [v]fprinte(): Add function
13:  e2e2c4fd = 13:  e2e2c4fd lib/io/fprintf/: [v]eprinte(): Add function
14:  058f311a = 14:  058f311a lib/, src/: Use eprinte() instead of its pattern
15:  3b1c3231 = 15:  3b1c3231 lib/: Use [v]fprinte() instead of its pattern
16:  47cf544a ! 16:  d94ded03 lib/io/syslog.h: SYSLOGE(): Add macro
    @@ lib/io/syslog.h
     +// system log errno
     +#define SYSLOGE(prio, fmt, ...)  do                                   \
     +{                                                                     \
    -+  SYSLOG(prio, "" fmt ": %s" __VA_OPT__(,) __VA_ARGS__, strerrno()) \
    ++  SYSLOG(prio, "" fmt ": %s" __VA_OPT__(,) __VA_ARGS__, strerrno()); \
     +} while (0)
     +
     +
17:  9faad6e1 = 17:  a16468a1 src/userdel.c: Fix error message
18:  e0290fcb = 18:  97d74781 lib/, src/: Use SYSLOGE() instead of its pattern
v6e
  • Add missing includes
$ git rd 
 -:  -------- >  1:  453bb132 lib/getdef.h: Add missing includes
 1:  da4c7959 =  2:  1aa42283 lib/io/fprintf/: eprintf(): Add function to print to stderr
 2:  13a80305 =  3:  e0f12df3 lib/, src/: Use eprintf() instead of its pattern
 3:  e1cddf24 =  4:  9478a434 lib/string/: strerrno(): Add function
 4:  767c2377 =  5:  7d03b42e lib/, src/: Use strerrno() instead of its pattern
 5:  7e6bef2e =  6:  869d2b44 src/su.c: Fix incorrect (non-matching) parentheses
 6:  a9900489 =  7:  96049602 lib/defines.h, lib/, src/: Redefine SYSLOG() as a variadic macro
 7:  ca6382ba =  8:  e542800a lib/: Move <syslog.h> wrappers to "io/syslog.h"
 8:  73336b3f =  9:  59a7bd7a lib/io/syslog.h: SYSLOG_C(): Split code to helper macro
 9:  063966cc = 10:  df5826c0 lib/io/syslog.h: Rename local variable
10:  ab24ab95 = 11:  7508615d lib/io/syslog.h: SYSLOG_C(): Use a single local variable
11:  07f77ecf = 12:  20a4f244 lib/io/syslog.h: SYSLOG_C(): Call setlocale(3) and free(3) unconditionally
12:  4d3b887d = 13:  7b2ce1f1 lib/io/fprintf/: [v]fprinte(): Add function
13:  e2e2c4fd = 14:  5b13bfba lib/io/fprintf/: [v]eprinte(): Add function
14:  058f311a = 15:  da1c2aac lib/, src/: Use eprinte() instead of its pattern
15:  3b1c3231 = 16:  1004d7e8 lib/: Use [v]fprinte() instead of its pattern
16:  d94ded03 = 17:  fa4d663d lib/io/syslog.h: SYSLOGE(): Add macro
17:  a16468a1 = 18:  42ff49da src/userdel.c: Fix error message
18:  97d74781 = 19:  68dfb3ae lib/, src/: Use SYSLOGE() instead of its pattern
v6f
  • Rebase
$ git rd 
 1:  453bb132 =  1:  0ac2e68c lib/getdef.h: Add missing includes
 2:  1aa42283 =  2:  acc8238c lib/io/fprintf/: eprintf(): Add function to print to stderr
 3:  e0f12df3 !  3:  4ebb63c2 lib/, src/: Use eprintf() instead of its pattern
    @@ src/chfn.c: int main (int argc, char **argv)
                        SYSLOG ((LOG_WARN, "Cannot determine the user name of the caller (UID %lu)",
                                 (unsigned long) getuid ()));
     @@ src/chfn.c: int main (int argc, char **argv)
    -    */
    -   if ((strlen (fullnm) + strlen (roomno) + strlen (workph) +
    -        strlen (homeph) + strlen (slop)) > (unsigned int) 80) {
    +           p = stpeprintf(p, e, ",%s", slop);
    + 
    +   if (p == e || p == NULL) {
     -          fprintf (stderr, _("%s: fields too long\n"), Prog);
     +          eprintf(_("%s: fields too long\n"), Prog);
                fail_exit (E_NOPERM);
        }
    -   SNPRINTF(new_gecos, "%s,%s,%s,%s%s%s",
    + 
     
      ## src/chgpasswd.c ##
     @@
 4:  9478a434 =  4:  2a615806 lib/string/: strerrno(): Add function
 5:  7d03b42e =  5:  fae8b792 lib/, src/: Use strerrno() instead of its pattern
 6:  869d2b44 =  6:  bdbe3523 src/su.c: Fix incorrect (non-matching) parentheses
 7:  96049602 =  7:  b170a21d lib/defines.h, lib/, src/: Redefine SYSLOG() as a variadic macro
 8:  e542800a =  8:  abdabe26 lib/: Move <syslog.h> wrappers to "io/syslog.h"
 9:  59a7bd7a =  9:  feda6e03 lib/io/syslog.h: SYSLOG_C(): Split code to helper macro
10:  df5826c0 = 10:  75cd1347 lib/io/syslog.h: Rename local variable
11:  7508615d = 11:  71818a6f lib/io/syslog.h: SYSLOG_C(): Use a single local variable
12:  20a4f244 = 12:  02ce55c6 lib/io/syslog.h: SYSLOG_C(): Call setlocale(3) and free(3) unconditionally
13:  7b2ce1f1 = 13:  c77c1be8 lib/io/fprintf/: [v]fprinte(): Add function
14:  5b13bfba = 14:  3a5f8825 lib/io/fprintf/: [v]eprinte(): Add function
15:  da1c2aac = 15:  a1a173d4 lib/, src/: Use eprinte() instead of its pattern
16:  1004d7e8 = 16:  17c5083e lib/: Use [v]fprinte() instead of its pattern
17:  fa4d663d = 17:  51640f21 lib/io/syslog.h: SYSLOGE(): Add macro
18:  42ff49da = 18:  3fb3b4c8 src/userdel.c: Fix error message
19:  68dfb3ae = 19:  55cd6cbc lib/, src/: Use SYSLOGE() instead of its pattern
v6g
  • Rebase
$ git rd 
 1:  0ac2e68c =  1:  6bc39aba lib/getdef.h: Add missing includes
 2:  acc8238c =  2:  4a57daa1 lib/io/fprintf/: eprintf(): Add function to print to stderr
 3:  4ebb63c2 =  3:  e75c9ff3 lib/, src/: Use eprintf() instead of its pattern
 4:  2a615806 =  4:  a46a8a0e lib/string/: strerrno(): Add function
 5:  fae8b792 =  5:  98555258 lib/, src/: Use strerrno() instead of its pattern
 6:  bdbe3523 =  6:  ad63c9e1 src/su.c: Fix incorrect (non-matching) parentheses
 7:  b170a21d =  7:  f56b7440 lib/defines.h, lib/, src/: Redefine SYSLOG() as a variadic macro
 8:  abdabe26 =  8:  d688bdb1 lib/: Move <syslog.h> wrappers to "io/syslog.h"
 9:  feda6e03 =  9:  4b42ef08 lib/io/syslog.h: SYSLOG_C(): Split code to helper macro
10:  75cd1347 = 10:  31706a0b lib/io/syslog.h: Rename local variable
11:  71818a6f = 11:  bd960db3 lib/io/syslog.h: SYSLOG_C(): Use a single local variable
12:  02ce55c6 = 12:  5164c736 lib/io/syslog.h: SYSLOG_C(): Call setlocale(3) and free(3) unconditionally
13:  c77c1be8 = 13:  c3e54019 lib/io/fprintf/: [v]fprinte(): Add function
14:  3a5f8825 = 14:  854399af lib/io/fprintf/: [v]eprinte(): Add function
15:  a1a173d4 = 15:  9d17e83b lib/, src/: Use eprinte() instead of its pattern
16:  17c5083e = 16:  f773e997 lib/: Use [v]fprinte() instead of its pattern
17:  51640f21 = 17:  93b6a5fc lib/io/syslog.h: SYSLOGE(): Add macro
18:  3fb3b4c8 = 18:  dc366523 src/userdel.c: Fix error message
19:  55cd6cbc = 19:  0a20d7bf lib/, src/: Use SYSLOGE() instead of its pattern
v7
  • Rebase
$ git rd 
 1:  6bc39aba =  1:  4c7cdd81 lib/getdef.h: Add missing includes
 2:  4a57daa1 =  2:  c5f7d1ba lib/io/fprintf/: eprintf(): Add function to print to stderr
 3:  e75c9ff3 !  3:  e9de5767 lib/, src/: Use eprintf() instead of its pattern
    @@ src/chpasswd.c: static void close_files (void)
                /* continue */
        }
     @@ src/chpasswd.c: int main (int argc, char **argv)
    -                                   }
    +                                           break;
                                }
      
     -                          fprintf (stderr,
    @@ src/lastlog.c: int main (int argc, char **argv)
     -          fprintf (stderr,
     -                   _("%s: Cannot get the size of %s: %s\n"),
     +          eprintf(_("%s: Cannot get the size of %s: %s\n"),
    -                    Prog, LASTLOG_FILE, strerror (errno));
    +                    Prog, _PATH_LASTLOG, strerror(errno));
                exit (EXIT_FAILURE);
        }
     
    @@ src/newgidmap.c: int main(int argc, char **argv)
     @@ src/newgidmap.c: int main(int argc, char **argv)
        }
      
    -   if (!sub_gid_open(O_RDONLY)) {
    +   if (want_subgid_file() && !sub_gid_open(O_RDONLY)) {
     -          fprintf (stderr,
     -                   _("%s: cannot open %s: %s\n"),
     +          eprintf(_("%s: cannot open %s: %s\n"),
    @@ src/newuidmap.c: int main(int argc, char **argv)
     @@ src/newuidmap.c: int main(int argc, char **argv)
        }
      
    -   if (!sub_uid_open(O_RDONLY)) {
    +   if (want_subuid_file() && !sub_uid_open(O_RDONLY)) {
     -          fprintf (stderr,
     -                   _("%s: cannot open %s: %s\n"),
     +          eprintf(_("%s: cannot open %s: %s\n"),
    @@ src/su.c: save_caller_context(void)
     @@ src/su.c: int main (int argc, char **argv)
        ret = pam_start (Prog, name, &conv, &pamh);
        if (PAM_SUCCESS != ret) {
    -           SYSLOG ((LOG_ERR, "pam_start: error %d", ret);
    --          fprintf (stderr,
    --                   _("%s: pam_start: error %d\n"),
    --                   Prog, ret));
    -+          eprintf(_("%s: pam_start: error %d\n"), Prog, ret));
    +           SYSLOG((LOG_ERR, "pam_start: error %d", ret));
    +-          fprintf(stderr, _("%s: pam_start: error %d\n"), Prog, ret);
    ++          eprintf(_("%s: pam_start: error %d\n"), Prog, ret);
                exit (1);
        }
      
    @@ src/useradd.c: static void faillog_reset (uid_t uid)
        }
     @@ src/useradd.c: static void lastlog_reset (uid_t uid)
      
    -   fd = open (LASTLOG_FILE, O_RDWR);
    +   fd = open(_PATH_LASTLOG, O_RDWR);
        if (-1 == fd) {
     -          fprintf (stderr,
     -                   _("%s: failed to open the lastlog file for UID %lu: %s\n"),
    @@ src/usermod.c: static void move_home (void)
        }
      }
     @@ src/usermod.c: static void update_lastlog (void)
    -   fd = open (LASTLOG_FILE, O_RDWR);
    +   fd = open(_PATH_LASTLOG, O_RDWR);
      
        if (-1 == fd) {
     -          fprintf (stderr,
 4:  a46a8a0e =  4:  c303977c lib/string/: strerrno(): Add function
 5:  98555258 !  5:  05f95c6f lib/, src/: Use strerrno() instead of its pattern
    @@ lib/tcbfuncs.c: static shadowtcb_status mkdir_leading (const char *name, uid_t u
     +                   shadow_progname, TCB_DIR, strerrno());
                goto out_free_path;
        }
    -   while ((ind = strchr (ptr, '/'))) {
    +   while (NULL != (ind = strchr(ptr, '/'))) {
     @@ lib/tcbfuncs.c: static shadowtcb_status mkdir_leading (const char *name, uid_t uid)
                if ((mkdir (dir, 0700) != 0) && (errno != EEXIST)) {
                        fprintf (shadow_logfd,
    @@ src/lastlog.c: int main (int argc, char **argv)
        /* Get the lastlog size */
        if (fstat (fileno (lastlogfile), &statbuf) != 0) {
                eprintf(_("%s: Cannot get the size of %s: %s\n"),
    --                   Prog, LASTLOG_FILE, strerror (errno));
    -+                  Prog, LASTLOG_FILE, strerrno());
    +-                   Prog, _PATH_LASTLOG, strerror(errno));
    ++                  Prog, _PATH_LASTLOG, strerrno());
                exit (EXIT_FAILURE);
        }
      
    @@ src/newgidmap.c: int main(int argc, char **argv)
     @@ src/newgidmap.c: int main(int argc, char **argv)
        }
      
    -   if (!sub_gid_open(O_RDONLY)) {
    +   if (want_subgid_file() && !sub_gid_open(O_RDONLY)) {
     -          eprintf(_("%s: cannot open %s: %s\n"),
     -                   Prog, sub_gid_dbname (), strerror (errno));
     +          eprintf(_("%s: cannot open %s: %s\n"), Prog, sub_gid_dbname(), strerrno());
    @@ src/newuidmap.c: int main(int argc, char **argv)
      
     @@ src/newuidmap.c: int main(int argc, char **argv)
      
    -   if (!sub_uid_open(O_RDONLY)) {
    +   if (want_subuid_file() && !sub_uid_open(O_RDONLY)) {
                eprintf(_("%s: cannot open %s: %s\n"),
     -                   Prog, sub_uid_dbname (), strerror (errno));
     +                  Prog, sub_uid_dbname(), strerrno());
    @@ src/useradd.c: static void faillog_reset (uid_t uid)
        }
      }
     @@ src/useradd.c: static void lastlog_reset (uid_t uid)
    -   fd = open (LASTLOG_FILE, O_RDWR);
    +   fd = open(_PATH_LASTLOG, O_RDWR);
        if (-1 == fd) {
                eprintf(_("%s: failed to open the lastlog file for UID %lu: %s\n"),
     -                   Prog, (unsigned long) uid, strerror (errno));
 6:  ad63c9e1 <  -:  -------- src/su.c: Fix incorrect (non-matching) parentheses
 7:  f56b7440 !  6:  5a448c24 lib/defines.h, lib/, src/: Redefine SYSLOG() as a variadic macro
    @@ lib/log.c: void dolastlog (
        if (lseek (fd, offset, SEEK_SET) != offset) {
     -          SYSLOG ((LOG_WARN,
     -                   "Can't read last lastlog entry for UID %lu in %s. Entry not updated.",
    --                   (unsigned long) pw->pw_uid, LASTLOG_FILE));
    +-                   (unsigned long) pw->pw_uid, _PATH_LASTLOG));
     +          SYSLOG(LOG_WARN,
     +                 "Can't read last lastlog entry for UID %lu in %s. Entry not updated.",
    -+                 (unsigned long) pw->pw_uid, LASTLOG_FILE);
    ++                 (unsigned long) pw->pw_uid, _PATH_LASTLOG);
                (void) close (fd);
                return;
        }
    @@ lib/log.c: err_write:
      err_close:
     -  SYSLOG ((LOG_WARN,
     -           "Can't write lastlog entry for UID %lu in %s: %m",
    --           (unsigned long) pw->pw_uid, LASTLOG_FILE));
    +-           (unsigned long) pw->pw_uid, _PATH_LASTLOG));
     +  SYSLOG(LOG_WARN,
     +         "Can't write lastlog entry for UID %lu in %s: %m",
    -+         (unsigned long) pw->pw_uid, LASTLOG_FILE);
    ++         (unsigned long) pw->pw_uid, _PATH_LASTLOG);
      }
     
      ## lib/pwdcheck.c ##
 8:  d688bdb1 =  7:  89a68bba lib/: Move <syslog.h> wrappers to "io/syslog.h"
 9:  4b42ef08 =  8:  de8b9cd4 lib/io/syslog.h: SYSLOG_C(): Split code to helper macro
10:  31706a0b =  9:  5cbca3af lib/io/syslog.h: Rename local variable
11:  bd960db3 = 10:  91bbde22 lib/io/syslog.h: SYSLOG_C(): Use a single local variable
12:  5164c736 = 11:  e32447c6 lib/io/syslog.h: SYSLOG_C(): Call setlocale(3) and free(3) unconditionally
13:  c3e54019 = 12:  fa2d4762 lib/io/fprintf/: [v]fprinte(): Add function
14:  854399af = 13:  d36ed519 lib/io/fprintf/: [v]eprinte(): Add function
15:  9d17e83b ! 14:  0a0f2c23 lib/, src/: Use eprinte() instead of its pattern
    @@ src/lastlog.c: int main (int argc, char **argv)
        /* Get the lastlog size */
        if (fstat (fileno (lastlogfile), &statbuf) != 0) {
     -          eprintf(_("%s: Cannot get the size of %s: %s\n"),
    --                  Prog, LASTLOG_FILE, strerrno());
    -+          eprinte(_("%s: Cannot get the size of %s"), Prog, LASTLOG_FILE);
    +-                  Prog, _PATH_LASTLOG, strerrno());
    ++          eprinte(_("%s: Cannot get the size of %s"), Prog, _PATH_LASTLOG);
                exit (EXIT_FAILURE);
        }
      
    @@ src/newgidmap.c: int main(int argc, char **argv)
     @@ src/newgidmap.c: int main(int argc, char **argv)
        }
      
    -   if (!sub_gid_open(O_RDONLY)) {
    +   if (want_subgid_file() && !sub_gid_open(O_RDONLY)) {
     -          eprintf(_("%s: cannot open %s: %s\n"), Prog, sub_gid_dbname(), strerrno());
     +          eprinte(_("%s: cannot open %s"), Prog, sub_gid_dbname());
                return EXIT_FAILURE;
    @@ src/newuidmap.c: int main(int argc, char **argv)
     @@ src/newuidmap.c: int main(int argc, char **argv)
        }
      
    -   if (!sub_uid_open(O_RDONLY)) {
    +   if (want_subuid_file() && !sub_uid_open(O_RDONLY)) {
     -          eprintf(_("%s: cannot open %s: %s\n"),
     -                  Prog, sub_uid_dbname(), strerrno());
     +          eprinte(_("%s: cannot open %s"), Prog, sub_uid_dbname());
    @@ src/useradd.c: static void faillog_reset (uid_t uid)
      }
     @@ src/useradd.c: static void lastlog_reset (uid_t uid)
      
    -   fd = open (LASTLOG_FILE, O_RDWR);
    +   fd = open(_PATH_LASTLOG, O_RDWR);
        if (-1 == fd) {
     -          eprintf(_("%s: failed to open the lastlog file for UID %lu: %s\n"),
     -                  Prog, (unsigned long) uid, strerrno());
    @@ src/usermod.c: prepend_range(const char *str, struct id_range_list_entry **head)
        }
        entry->next = *head;
     @@ src/usermod.c: static void update_lastlog (void)
    -   fd = open (LASTLOG_FILE, O_RDWR);
    +   fd = open(_PATH_LASTLOG, O_RDWR);
      
        if (-1 == fd) {
     -          eprintf(_("%s: failed to copy the lastlog entry of user %lu to user %lu: %s\n"),
16:  f773e997 ! 15:  350da966 lib/: Use [v]fprinte() instead of its pattern
    @@ lib/tcbfuncs.c: static shadowtcb_status mkdir_leading (const char *name, uid_t u
     +                  shadow_progname, TCB_DIR);
                goto out_free_path;
        }
    -   while ((ind = strchr (ptr, '/'))) {
    +   while (NULL != (ind = strchr(ptr, '/'))) {
     @@ lib/tcbfuncs.c: static shadowtcb_status mkdir_leading (const char *name, uid_t uid)
                        return SHADOWTCB_FAILURE;
                }
17:  93b6a5fc = 16:  64d4993c lib/io/syslog.h: SYSLOGE(): Add macro
18:  dc366523 = 17:  dfb25c6c src/userdel.c: Fix error message
19:  0a20d7bf = 18:  3b1b87e4 lib/, src/: Use SYSLOGE() instead of its pattern

@alejandro-colomar
Copy link
Collaborator Author

I recommend reviewing the second commit with

$ git show HEAD^ --color-words=.

@alejandro-colomar alejandro-colomar linked an issue Jul 13, 2025 that may be closed by this pull request
@alejandro-colomar alejandro-colomar force-pushed the eprintf branch 3 times, most recently from 5fa8f9a to c3af808 Compare July 13, 2025 20:44
@ikerexxe
Copy link
Collaborator

I have some reservations about commits 1 and 2. Specifically, the new interface introduced isn't something I've commonly seen in other projects, even though I'm aware of its mention in the GCC documentation. From my perspective, it doesn't appear to offer a significant benefit here.

Furthermore, I'm concerned that commit 2 introduces changes across many files, which could make it quite challenging for distribution maintainers to backport future changes to their distributions. This could lead to a lot of friction and messy patch applications down the line.

On the other hand, I'm fine with the changes in commits 3 and 4. They look good to me.

@alejandro-colomar
Copy link
Collaborator Author

alejandro-colomar commented Jul 17, 2025

I have some reservations about commits 1 and 2. Specifically, the new interface introduced isn't something I've commonly seen in other projects, even though I'm aware of its mention in the GCC documentation. From my perspective, it doesn't appear to offer a significant benefit here.

Furthermore, I'm concerned that commit 2 introduces changes across many files, which could make it quite challenging for distribution maintainers to backport future changes to their distributions. This could lead to a lot of friction and messy patch applications down the line.

Yeah, I guess this would be a lot of work for distros. I'm fine not applying it for now; we can come back to it in the future.

On the other hand, I'm fine with the changes in commits 3 and 4. They look good to me.

I will split patches 3 and 4 to allow applying them separately.

@alejandro-colomar
Copy link
Collaborator Author

alejandro-colomar commented Jul 17, 2025

On the other hand, I plan to do a lot of work on error messages after this eprintf() patch, trying to unify them and use strerror(errno) more, which would significantly reduce translation work. This would similarly force distros to rebase their patches, so I don't see eprintf() as a huge added problem here.

But yeah, we have lower hanging fruits for now.

@alejandro-colomar alejandro-colomar marked this pull request as draft July 20, 2025 13:40
@alejandro-colomar alejandro-colomar marked this pull request as ready for review July 22, 2025 23:25
@alejandro-colomar
Copy link
Collaborator Author

alejandro-colomar commented Jul 22, 2025

@ikerexxe

I think we now have strong reasons to merge this. See the bug fixed in a call to SYSLOG() (and fprintf()).

Edit: I've found more bugs after spending more time looking at these calls.

@alejandro-colomar alejandro-colomar linked an issue Jul 22, 2025 that may be closed by this pull request
@alejandro-colomar alejandro-colomar changed the title Add and use eprintf() Add and use eprintf(), and de-weirdify SYSLOG(()) Jul 22, 2025
@alejandro-colomar alejandro-colomar changed the title Add and use eprintf(), and de-weirdify SYSLOG(()) Add and use eprintf() and strerrno(), and de-weirdify SYSLOG(()) Jul 22, 2025
@alejandro-colomar alejandro-colomar force-pushed the eprintf branch 6 times, most recently from 97d7478 to 68dfb3a Compare July 23, 2025 20:51
@alejandro-colomar alejandro-colomar force-pushed the eprintf branch 2 times, most recently from 55cd6cb to 0a20d7b Compare August 16, 2025 20:32
Signed-off-by: Alejandro Colomar <[email protected]>
This will allow having shorter lines for writing to stderr.

This name is commonly used in other projects, it seems (see link below).

Link: <https://gcc.gnu.org/onlinedocs/gcc-3.1.1/cpp/Variadic-Macros.html>
Signed-off-by: Alejandro Colomar <[email protected]>
Signed-off-by: Alejandro Colomar <[email protected]>
The double parentheses were used to fake a variadic macro with a
non-variadic one.  With a variadic macro, we remove the weird double
parentheses that were needed to call this macro, which BTW were
error-prone (see the bug fixed in the previous commit).

Signed-off-by: Alejandro Colomar <[email protected]>
The name of this macro makes it more evident what it does.  It's a
C-locale version of syslog(3).  We need to implement it as a macro
so that arguments such as strerror(3) are evaluated after setting
the C locale.  This would be impossible with a function.

Signed-off-by: Alejandro Colomar <[email protected]>
There's no need for two variables, and this avoids one assignment.

Signed-off-by: Alejandro Colomar <[email protected]>
…nally

Both setlocale(3) and free(3) are okay to call with a null pointer.

Signed-off-by: Alejandro Colomar <[email protected]>
This function preserves errno, so that a following syslog(3) call still
has the previous errno value.

Signed-off-by: Alejandro Colomar <[email protected]>
Signed-off-by: Alejandro Colomar <[email protected]>
Signed-off-by: Alejandro Colomar <[email protected]>
Having such long and complex format strings and variadic arguments is
error-prone, as can be seen in the previous commit, which fixes a bug of
this kind.

Signed-off-by: Alejandro Colomar <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Missing closing parenthesis in syslog(3) call Writing to wrong stream

2 participants