Elliot Hughes wrote:
> yeah, _PATH_DEFPATH is the only path string we offer anyway, but it should
> be reasonable for this kind of use case.

Thanks. I'm using it now, in the patch below.

> > And which binaries exist in /bin = /system/bin ?
> 
> "all the usual unix stuff [that we have]". the other stuff is probably a
> mistake, but nothing i cared enough about to fight.

Thanks for the info. Indeed, some of the binaries work (such as /bin/sh,
/bin/ls), while others don't:

$ /bin/df
/bin/df: 1: Syntax error: word unexpected (expecting ")")

Probably this doesn't get reported, because people don't know about
these binaries :)

Bruno


2026-11-03  Bruno Haible  <[email protected]>

        findprog*: Don't use the empty PATH as fallback on most platforms.
        Reported by Pádraig Brady in
        <https://lists.gnu.org/archive/html/bug-gnulib/2026-11/msg00010.html>.
        * lib/findprog.c: Include <paths.h>.
        (find_in_path): If confstr fails, just abort. On Android, use
        _PATH_DEFPATH, as recommended by Elliott Hughes.
        * lib/findprog-in.c: Include <paths.h>.
        (find_in_given_path): If confstr fails, just abort. On Android, use
        _PATH_DEFPATH, as recommended by Elliott Hughes.

diff --git a/lib/findprog-in.c b/lib/findprog-in.c
index d937f7c834..24cd2f9014 100644
--- a/lib/findprog-in.c
+++ b/lib/findprog-in.c
@@ -26,6 +26,9 @@
 #include <string.h>
 #include <unistd.h>
 #include <sys/stat.h>
+#ifdef __ANDROID__
+# include <paths.h>
+#endif
 
 #include "filename.h"
 #include "concat-filename.h"
@@ -223,10 +226,18 @@ find_in_given_path (const char *progname, const char 
*path,
          dependent.  On POSIX systems, it is confstr (_CS_PATH).  */
       #if HAVE_CONFSTR
       int ret = confstr (_CS_PATH, default_path, sizeof (default_path));
-      if (ret == 0 || ret > sizeof (default_path))
-      #endif
-        default_path[0] = '\0';
+      if (ret == 0)
+        /* The platform has confstr(), but it does not support _CS_PATH.  */
+        abort ();
+      if (ret > sizeof (default_path))
+        /* MAX_DEFAULT_PATH_SIZE is too small.  Increase it.  */
+        abort ();
       path = default_path;
+      #elif defined __ANDROID__
+      path = _PATH_DEFPATH;
+      #else /* native Windows, Minix */
+      path = "";
+      #endif
     }
 
   {
diff --git a/lib/findprog.c b/lib/findprog.c
index 2d321dc0d9..2a017e8686 100644
--- a/lib/findprog.c
+++ b/lib/findprog.c
@@ -27,6 +27,9 @@
 #if !(defined _WIN32 || defined __CYGWIN__ || defined __EMX__ || defined 
__DJGPP__)
 # include <sys/stat.h>
 #endif
+#ifdef __ANDROID__
+# include <paths.h>
+#endif
 
 /* Avoid collision between findprog.c and findprog-lgpl.c.  */
 #if IN_FINDPROG_LGPL || ! GNULIB_FINDPROG_LGPL
@@ -69,7 +72,7 @@ find_in_path (const char *progname)
        the current directory.  PATH is not used.  */
     return progname;
 
-  char *path = getenv ("PATH");
+  const char *path = getenv ("PATH");
   char default_path[MAX_DEFAULT_PATH_SIZE];
   if (path == NULL)
     {
@@ -77,24 +80,33 @@ find_in_path (const char *progname)
          dependent.  On POSIX systems, it is confstr (_CS_PATH).  */
       #if HAVE_CONFSTR
       int ret = confstr (_CS_PATH, default_path, sizeof (default_path));
-      if (ret == 0 || ret > sizeof (default_path))
-      #endif
-        default_path[0] = '\0';
+      if (ret == 0)
+        /* The platform has confstr(), but it does not support _CS_PATH.  */
+        abort ();
+      if (ret > sizeof (default_path))
+        /* MAX_DEFAULT_PATH_SIZE is too small.  Increase it.  */
+        abort ();
       path = default_path;
+      #elif defined __ANDROID__
+      path = _PATH_DEFPATH;
+      #else /* native Windows, Minix */
+      path = "";
+      #endif
     }
   if (*path == '\0')
     return progname;
 
   /* Make a copy, to prepare for destructive modifications.  */
+  char *path_copy;
 # if !IN_FINDPROG_LGPL
-  path = xstrdup (path);
+  path_copy = xstrdup (path);
 # else
-  path = strdup (path);
-  if (path == NULL)
+  path_copy = strdup (path);
+  if (path_copy == NULL)
     /* Out of memory.  */
     return progname;
 # endif
-  for (char *path_rest = path; ; )
+  for (char *path_rest = path_copy; ; )
     {
       /* Extract next directory in PATH.  */
       const char *dir = path_rest;
@@ -117,7 +129,7 @@ find_in_path (const char *progname)
       if (progpathname == NULL)
         {
           /* Out of memory.  */
-          free (path);
+          free (path_copy);
           return progname;
         }
 # endif
@@ -149,7 +161,7 @@ find_in_path (const char *progname)
                   if (progpathname == NULL)
                     {
                       /* Out of memory.  */
-                      free (path);
+                      free (path_copy);
                       return progname;
                     }
 # endif
@@ -158,7 +170,7 @@ find_in_path (const char *progname)
                   memcpy (progpathname + 2, progname, strlen (progname) + 1);
                 }
 
-              free (path);
+              free (path_copy);
               return progpathname;
             }
         }
@@ -172,7 +184,7 @@ find_in_path (const char *progname)
     }
 
   /* Not found in PATH.  An error will be signalled at the first call.  */
-  free (path);
+  free (path_copy);
   return progname;
 #endif
 }




Reply via email to