public inbox for cygwin@cygwin.com
 help / color / mirror / Atom feed
* Cygwin's execlp() does not work with an empty $PATH element
@ 2022-06-26 15:09 Lavrentiev, Anton (NIH/NLM/NCBI) [C]
  2022-06-26 16:26 ` Lavrentiev, Anton (NIH/NLM/NCBI) [C]
  2022-06-27 11:16 ` Takashi Yano
  0 siblings, 2 replies; 4+ messages in thread
From: Lavrentiev, Anton (NIH/NLM/NCBI) [C] @ 2022-06-26 15:09 UTC (permalink / raw)
  To: 'cygwin@cygwin.com'

Hi all,

An empty PATH element (":xxx" or "xxx::xxx" or "xxx:") is to be considered as the current directory (from the very first days of Unix).

However, Cygwin does not seem to obey the rule.

Consider the following simple C program:

$ cat hello.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

int main(int argc, const char* argv[])
{
    if (argc < 2) {
        const char* prog = strrchr(argv[0], '/');
        if (!prog++)
           prog = argv[0];
        execlp(prog, prog, "Hello", NULL);  // execute just by the program name
        perror("exec");
        return 1;
    }
    printf("%s\n", argv[1]);
    return 0;
}

Now compare the execution on Linux and Cygwin:

Linux:

$ gcc -Wall -o hello hello.c
$ hello
bash: hello: command not found
$ ./hello
exec: No such file or directory
$ PATH=".:$PATH" ./hello
Hello
$ PATH=":$PATH" ./hello
Hello
$ PATH="${PATH}:" ./hello
Hello

Cygwin:

$ gcc -Wall -o hello hello.c
$ hello
-bash: hello: command not found
$ ./hello
exec: No such file or directory
$ PATH=".:$PATH" ./hello
Hello
$ PATH=":$PATH" ./hello
exec: No such file or directory
$ PATH="${PATH}:" ./hello
exec: No such file or directory

As you can see, the execution failed when an empty PATH element was added on Cygwin
(yet it was perfectly fine on Linux).

Anton Lavrentiev
Contractor NIH/NLM/NCBI


^ permalink raw reply	[flat|nested] 4+ messages in thread

* RE: Cygwin's execlp() does not work with an empty $PATH element
  2022-06-26 15:09 Cygwin's execlp() does not work with an empty $PATH element Lavrentiev, Anton (NIH/NLM/NCBI) [C]
@ 2022-06-26 16:26 ` Lavrentiev, Anton (NIH/NLM/NCBI) [C]
  2022-06-27 11:16 ` Takashi Yano
  1 sibling, 0 replies; 4+ messages in thread
From: Lavrentiev, Anton (NIH/NLM/NCBI) [C] @ 2022-06-26 16:26 UTC (permalink / raw)
  To: 'cygwin@cygwin.com'

There's another discrepancy for execlp() on Cygwin.  In the absence of the PATH environment, it should consider the current directory first, then look up somewhere else.
And it does so on Linux!  Not on Cygwin, though.  Please take a look below:

Linux:

$ ./hello
exec: No such file or directory
$ unset PATH
$ echo $PATH

$ ./hello
Hello

Cygwin:

$ ./hello
exec: No such file or directory
$ unset PATH

$ echo $PATH
$ ./hello
exec: No such file or directory

Anton Lavrentiev
Contractor NIH/NLM/NCBI

> -----Original Message-----
> From: Cygwin <cygwin-bounces+lavr=ncbi.nlm.nih.gov@cygwin.com> On Behalf Of Lavrentiev,
> Anton (NIH/NLM/NCBI) [C] via Cygwin
> Sent: Sunday, June 26, 2022 11:10 AM
> To: 'cygwin@cygwin.com' <cygwin@cygwin.com>
> Subject: [EXTERNAL] Cygwin's execlp() does not work with an empty $PATH element
> 
> Hi all,
> 
> An empty PATH element (":xxx" or "xxx::xxx" or "xxx:") is to be considered as the current
> directory (from the very first days of Unix).
> 
> However, Cygwin does not seem to obey the rule.
> 
> Consider the following simple C program:
> 
> $ cat hello.c
> #include <stdio.h>
> #include <stdlib.h>
> #include <string.h>
> #include <unistd.h>
> 
> int main(int argc, const char* argv[])
> {
>     if (argc < 2) {
>         const char* prog = strrchr(argv[0], '/');
>         if (!prog++)
>            prog = argv[0];
>         execlp(prog, prog, "Hello", NULL);  // execute just by the program name
>         perror("exec");
>         return 1;
>     }
>     printf("%s\n", argv[1]);
>     return 0;
> }
> 
> Now compare the execution on Linux and Cygwin:
> 
> Linux:
> 
> $ gcc -Wall -o hello hello.c
> $ hello
> bash: hello: command not found
> $ ./hello
> exec: No such file or directory
> $ PATH=".:$PATH" ./hello
> Hello
> $ PATH=":$PATH" ./hello
> Hello
> $ PATH="${PATH}:" ./hello
> Hello
> 
> Cygwin:
> 
> $ gcc -Wall -o hello hello.c
> $ hello
> -bash: hello: command not found
> $ ./hello
> exec: No such file or directory
> $ PATH=".:$PATH" ./hello
> Hello
> $ PATH=":$PATH" ./hello
> exec: No such file or directory
> $ PATH="${PATH}:" ./hello
> exec: No such file or directory
> 
> As you can see, the execution failed when an empty PATH element was added on Cygwin
> (yet it was perfectly fine on Linux).
> 
> Anton Lavrentiev
> Contractor NIH/NLM/NCBI
> 
> 
> --
> Problem reports:
> https://gcc02.safelinks.protection.outlook.com/?url=https%3A%2F%2Fcygwin.com%2Fproblems.ht
> ml&amp;data=05%7C01%7Clavr%40ncbi.nlm.nih.gov%7C4f115d6612d84622f36e08da578602f6%7C14b7757
> 8977342d58507251ca2dc2b06%7C0%7C0%7C637918530342421084%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4
> wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C3000%7C%7C%7C&amp;sdata=5W%2FkRL
> P2C5dOS1mAwXbXjeW3jLCNm3Kn%2BCFMJbPlgyo%3D&amp;reserved=0
> FAQ:
> https://gcc02.safelinks.protection.outlook.com/?url=https%3A%2F%2Fcygwin.com%2Ffaq%2F&amp;
> data=05%7C01%7Clavr%40ncbi.nlm.nih.gov%7C4f115d6612d84622f36e08da578602f6%7C14b77578977342
> d58507251ca2dc2b06%7C0%7C0%7C637918530342421084%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMD
> AiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C3000%7C%7C%7C&amp;sdata=vYE4PpDSlT6%2Fw
> jApZyC8r1BjQULY4MmBH2nUJIXE3BQ%3D&amp;reserved=0
> Documentation:
> https://gcc02.safelinks.protection.outlook.com/?url=https%3A%2F%2Fcygwin.com%2Fdocs.html&a
> mp;data=05%7C01%7Clavr%40ncbi.nlm.nih.gov%7C4f115d6612d84622f36e08da578602f6%7C14b77578977
> 342d58507251ca2dc2b06%7C0%7C0%7C637918530342421084%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjA
> wMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C3000%7C%7C%7C&amp;sdata=pbcpGI8Ykvb5
> UQlP%2FOT6G2ZUXloiARlZvax0NhyO2t0%3D&amp;reserved=0
> Unsubscribe info:
> https://gcc02.safelinks.protection.outlook.com/?url=https%3A%2F%2Fcygwin.com%2Fml%2F%23uns
> ubscribe-
> simple&amp;data=05%7C01%7Clavr%40ncbi.nlm.nih.gov%7C4f115d6612d84622f36e08da578602f6%7C14b
> 77578977342d58507251ca2dc2b06%7C0%7C0%7C637918530342421084%7CUnknown%7CTWFpbGZsb3d8eyJWIjo
> iMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C3000%7C%7C%7C&amp;sdata=DGMP
> SVCqWNO6qKi6BCqKvvWxBD4x2m2vUfBCIHfI9Ts%3D&amp;reserved=0


^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: Cygwin's execlp() does not work with an empty $PATH element
  2022-06-26 15:09 Cygwin's execlp() does not work with an empty $PATH element Lavrentiev, Anton (NIH/NLM/NCBI) [C]
  2022-06-26 16:26 ` Lavrentiev, Anton (NIH/NLM/NCBI) [C]
@ 2022-06-27 11:16 ` Takashi Yano
  2022-06-27 12:15   ` Takashi Yano
  1 sibling, 1 reply; 4+ messages in thread
From: Takashi Yano @ 2022-06-27 11:16 UTC (permalink / raw)
  To: cygwin

On Sun, 26 Jun 2022 15:09:34 +0000
"Lavrentiev, Anton \(NIH/NLM/NCBI\) \[C\] wrote:
> An empty PATH element (":xxx" or "xxx::xxx" or "xxx:") is to be considered as the current directory (from the very first days of Unix).
> 
> However, Cygwin does not seem to obey the rule.
> 
> Consider the following simple C program:
> 
> $ cat hello.c
> #include <stdio.h>
> #include <stdlib.h>
> #include <string.h>
> #include <unistd.h>
> 
> int main(int argc, const char* argv[])
> {
>     if (argc < 2) {
>         const char* prog = strrchr(argv[0], '/');
>         if (!prog++)
>            prog = argv[0];
>         execlp(prog, prog, "Hello", NULL);  // execute just by the program name
>         perror("exec");
>         return 1;
>     }
>     printf("%s\n", argv[1]);
>     return 0;
> }
> 
> Now compare the execution on Linux and Cygwin:
> 
> Linux:
> 
> $ gcc -Wall -o hello hello.c
> $ hello
> bash: hello: command not found
> $ ./hello
> exec: No such file or directory
> $ PATH=".:$PATH" ./hello
> Hello
> $ PATH=":$PATH" ./hello
> Hello
> $ PATH="${PATH}:" ./hello
> Hello
> 
> Cygwin:
> 
> $ gcc -Wall -o hello hello.c
> $ hello
> -bash: hello: command not found
> $ ./hello
> exec: No such file or directory
> $ PATH=".:$PATH" ./hello
> Hello
> $ PATH=":$PATH" ./hello
> exec: No such file or directory
> $ PATH="${PATH}:" ./hello
> exec: No such file or directory
> 
> As you can see, the execution failed when an empty PATH element was added on Cygwin
> (yet it was perfectly fine on Linux).

How about the following patch?

diff --git a/winsup/cygwin/spawn.cc b/winsup/cygwin/spawn.cc
index e0f1247e1..8fe9d089f 100644
--- a/winsup/cygwin/spawn.cc
+++ b/winsup/cygwin/spawn.cc
@@ -118,8 +118,10 @@ find_exec (const char *name, path_conv& buf, const char *search,
      the name of an environment variable. */
   if (strchr (search, '/'))
     *stpncpy (tmp, search, NT_MAX_PATH - 1) = '\0';
-  else if (has_slash || isdrive (name) || !(path = getenv (search)) || !*path)
+  else if (has_slash || isdrive (name))
     goto errout;
+  else if (!(path = getenv (search)) || !*path)
+    strcpy (tmp, "."); /* Search the current directory when PATH is absent */
   else
     *stpncpy (tmp, path, NT_MAX_PATH - 1) = '\0';
 
@@ -134,7 +136,9 @@ find_exec (const char *name, path_conv& buf, const char *search,
 	 already tried that.  */
       if ((opt & FE_CWD) && (tmp_path[0] == '\0'
 			     || (tmp_path[0] == '.' && tmp_path[1] == '\0')))
-	continue;
+	goto next;
+      else if (tmp_path[0] == '\0') /* An empty path means the current dir. */
+	eotmp = stpcpy (tmp_path, ".");
 
       *eotmp++ = '/';
       stpcpy (eotmp, name);
@@ -146,7 +150,7 @@ find_exec (const char *name, path_conv& buf, const char *search,
       if ((suffix = perhaps_suffix (tmp_path, buf, err1, opt)) != NULL)
 	{
 	  if (buf.has_acls () && check_file_access (buf, X_OK, true))
-	    continue;
+	    goto next;
 	  /* Overwrite potential symlink target with original path.
 	     See comment preceeding this method. */
 	  buf.set_posix (tmp_path);
@@ -154,8 +158,13 @@ find_exec (const char *name, path_conv& buf, const char *search,
 	  goto out;
 	}
 
+next:
+      if (*path == '\0')
+	break;
+      if (*path == ':')
+	path++;
     }
-  while (*path && *++path);
+  while (true);
 
  errout:
   /* Couldn't find anything in the given path.

-- 
Takashi Yano <takashi.yano@nifty.ne.jp>

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: Cygwin's execlp() does not work with an empty $PATH element
  2022-06-27 11:16 ` Takashi Yano
@ 2022-06-27 12:15   ` Takashi Yano
  0 siblings, 0 replies; 4+ messages in thread
From: Takashi Yano @ 2022-06-27 12:15 UTC (permalink / raw)
  To: cygwin

On Mon, 27 Jun 2022 20:16:36 +0900
Takashi Yano wrote:
> How about the following patch?

This is better a bit.

diff --git a/winsup/cygwin/spawn.cc b/winsup/cygwin/spawn.cc
index e0f1247e1..292cd5a42 100644
--- a/winsup/cygwin/spawn.cc
+++ b/winsup/cygwin/spawn.cc
@@ -95,6 +95,7 @@ find_exec (const char *name, path_conv& buf, const char *search,
   char *tmp = tp.c_get ();
   bool has_slash = !!strpbrk (name, "/\\");
   int err = 0;
+  bool eopath = false;
 
   debug_printf ("find_exec (%s)", name);
 
@@ -118,8 +119,10 @@ find_exec (const char *name, path_conv& buf, const char *search,
      the name of an environment variable. */
   if (strchr (search, '/'))
     *stpncpy (tmp, search, NT_MAX_PATH - 1) = '\0';
-  else if (has_slash || isdrive (name) || !(path = getenv (search)) || !*path)
+  else if (has_slash || isdrive (name))
     goto errout;
+  else if (!(path = getenv (search)) || !*path)
+    strcpy (tmp, "."); /* Search the current directory when PATH is absent */
   else
     *stpncpy (tmp, path, NT_MAX_PATH - 1) = '\0';
 
@@ -130,11 +133,17 @@ find_exec (const char *name, path_conv& buf, const char *search,
   do
     {
       char *eotmp = strccpy (tmp_path, &path, ':');
+      if (*path)
+	path++;
+      else
+	eopath = true;
       /* An empty path or '.' means the current directory, but we've
 	 already tried that.  */
       if ((opt & FE_CWD) && (tmp_path[0] == '\0'
 			     || (tmp_path[0] == '.' && tmp_path[1] == '\0')))
 	continue;
+      else if (tmp_path[0] == '\0') /* An empty path means the current dir. */
+	eotmp = stpcpy (tmp_path, ".");
 
       *eotmp++ = '/';
       stpcpy (eotmp, name);
@@ -155,7 +164,7 @@ find_exec (const char *name, path_conv& buf, const char *search,
 	}
 
     }
-  while (*path && *++path);
+  while (!eopath);
 
  errout:
   /* Couldn't find anything in the given path.


-- 
Takashi Yano <takashi.yano@nifty.ne.jp>

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2022-06-27 12:15 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-06-26 15:09 Cygwin's execlp() does not work with an empty $PATH element Lavrentiev, Anton (NIH/NLM/NCBI) [C]
2022-06-26 16:26 ` Lavrentiev, Anton (NIH/NLM/NCBI) [C]
2022-06-27 11:16 ` Takashi Yano
2022-06-27 12:15   ` Takashi Yano

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).