* lib/progname.c: Don’t include stdio.h or stdlib.h.
(set_program_name): Omit dynamic check that (with current glibc
optimization) drags in fwrite even when unlocked I/O is wanted.
The check was not all that useful in practice and we now have a
static one anyway (which admittedly is not that useful either).
Prefer memcmp to strncmp when equivalent, for clarity.
* lib/progname.h: Include arg-nonnull.h and declare
set_program_name with _GL_ARG_NONNULL.
* modules/progname (Depends-on): Add snippet/arg-nonnull.
---
 ChangeLog        | 11 +++++++++++
 lib/progname.c   | 21 +++------------------
 lib/progname.h   |  4 +++-
 modules/progname |  1 +
 4 files changed, 18 insertions(+), 19 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 0837b6c821..c8f5c0da3a 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,16 @@
 2025-09-05  Paul Eggert  <[email protected]>
 
+       progname: static check instead of dynamic
+       * lib/progname.c: Don’t include stdio.h or stdlib.h.
+       (set_program_name): Omit dynamic check that (with current glibc
+       optimization) drags in fwrite even when unlocked I/O is wanted.
+       The check was not all that useful in practice and we now have a
+       static one anyway (which admittedly is not that useful either).
+       Prefer memcmp to strncmp when equivalent, for clarity.
+       * lib/progname.h: Include arg-nonnull.h and declare
+       set_program_name with _GL_ARG_NONNULL.
+       * modules/progname (Depends-on): Add snippet/arg-nonnull.
+
        propername-lite: simplify USE_MBRTOC32 away
        * lib/propername-lite.c (USE_MBRTOC32): Remove.
        Replace its use with HAVE_UCHAR_H.
diff --git a/lib/progname.c b/lib/progname.c
index 4a45ca3490..4b0c9cc6ac 100644
--- a/lib/progname.c
+++ b/lib/progname.c
@@ -23,8 +23,6 @@
 #include "progname.h"
 
 #include <errno.h> /* get program_invocation_name declaration */
-#include <stdio.h>
-#include <stdlib.h>
 #include <string.h>
 
 
@@ -43,22 +41,9 @@ set_program_name (const char *argv0)
      But the name of the temporary executable is a detail that should not be
      visible to the end user and to the test suite.
      Remove this "<dirname>/.libs/" or "<dirname>/.libs/lt-" prefix here.  */
-  const char *slash;
-  const char *base;
-
-  /* Sanity check.  POSIX requires the invoking process to pass a non-NULL
-     argv[0].  */
-  if (argv0 == NULL)
-    {
-      /* It's a bug in the invoking program.  Help diagnosing it.  */
-      fputs ("A NULL argv[0] was passed through an exec system call.\n",
-             stderr);
-      abort ();
-    }
-
-  slash = strrchr (argv0, '/');
-  base = (slash != NULL ? slash + 1 : argv0);
-  if (base - argv0 >= 7 && strncmp (base - 7, "/.libs/", 7) == 0)
+  char const *slash = strrchr (argv0, '/');
+  char const *base = slash ? slash + 1 : argv0;
+  if (7 <= base - argv0 && memcmp (base - 7, "/.libs/", 7) == 0)
     {
       argv0 = base;
       if (strncmp (base, "lt-", 3) == 0)
diff --git a/lib/progname.h b/lib/progname.h
index 509f0da791..dbfefd9269 100644
--- a/lib/progname.h
+++ b/lib/progname.h
@@ -22,6 +22,7 @@
      set_program_name (argv[0]);
  */
 
+#include "arg-nonnull.h"
 
 #ifdef __cplusplus
 extern "C" {
@@ -34,7 +35,8 @@ extern const char *program_name;
 /* Set program_name, based on argv[0].
    argv0 must be a string allocated with indefinite extent, and must not be
    modified after this call.  */
-extern void set_program_name (const char *argv0);
+extern void set_program_name (const char *argv0)
+  _GL_ARG_NONNULL ((1));
 
 #if ENABLE_RELOCATABLE
 
diff --git a/modules/progname b/modules/progname
index a9a53b947a..fc244e2b86 100644
--- a/modules/progname
+++ b/modules/progname
@@ -6,6 +6,7 @@ lib/progname.h
 lib/progname.c
 
 Depends-on:
+snippet/arg-nonnull
 
 configure.ac:
 AC_CHECK_DECLS([program_invocation_name], [], [], [#include <errno.h>])
-- 
2.48.1


Reply via email to