public inbox for cygwin@cygwin.com
 help / color / mirror / Atom feed
* Command line arguments parsing problem
@ 2000-05-30 20:16 bogus
  2000-05-31 10:46 ` MarketLogix
  0 siblings, 1 reply; 4+ messages in thread
From: bogus @ 2000-05-30 20:16 UTC (permalink / raw)
  To: cygwin

I have many troubles with command line arguments parsing when I run a
non-cygwin program from bash. The problems occurs when I try to put
literal double quotation marks in arguments.
Here is a simple example that demonstrates the problem:

/tmp $ cat <<EOF > print_args.c
> #include <stdio.h>
>
> int
> main(int argc, char** argv) {
>   int i;
>   for(i = 1; i < argc; i++) {
>     printf("%d: %s\n", i, argv[i]);
>   }
>   exit(0);
> }
> EOF
/tmp $ gcc -o print_args_cygwin print_args.c
/tmp $ gcc -o print_args_nocygwin -mno-cygwin print_args.c
/tmp $ ./print_args_cygwin.exe '" "'
1: " "
/tmp $ ./print_args_nocygwin.exe '" "'
1: "
2: "

As you can see the non-cygwin program gets an inconsistent argv.

After some investigations, I discovered that a spawned windows
process doesn't get directly an array of disjointed arguments but a
command line it has to parse itself in order to build argv.
To build the command line that will be given to a sub-process, the
current cygwin implementation uses double quote marks to enclose
arguments while literal double quote marks are doubled.
For some unknown reasons, it appears that the non-cygwin programs
don't parse that syntax properly, but instead they seem to handle
correctly another syntax that uses backslashes to protect literal
double quote marks.
Eventually, I wrote the small patch below, so that cygwin uses the
backslash syntax. It seems to work fine, but as I'm a cygwin newbie,
it might actually be completly broken, and maybe there are good reasons
for using the double double quote marks syntax instead of the backslash
syntax. I'm waiting for your comments.

Regards,

Pierre Bogossian

PS: This patch doesn't fix the symmetrical problem: when a cygwin
program is called from a windows shell. But as I'm not using windows
shells anymore, that doesn't bother me that much ;-)

---

diff -r -up winsup-src-20000527-orig/cygwin/dcrt0.cc winsup-src-20000527-patched/cygwin/dcrt0.cc
--- winsup-src-20000527-orig/cygwin/dcrt0.cc	Mon May 22 05:55:16 2000
+++ winsup-src-20000527-patched/cygwin/dcrt0.cc	Mon May 29 04:19:34 2000
@@ -281,17 +281,21 @@ quoted (char *cmd, int winshell)
   /* When running as a child of a cygwin process, the quoted
      characters should have been placed here by spawn_guts, so
      we'll just pinch them out of the command string unless
-     they're quoted with a preceding \ */
+     they're quoted with an odd number of preceding \ */
   strcpy (cmd, cmd + 1);
-  while (*cmd)
+  while (1)
     {
-      if (*cmd != quote)
-	cmd++;
-      else if (cmd[1] == quote)
-	strcpy (cmd++, cmd + 1);
+      char *fpbs;           /* The first preceding backslash */
+      int bs_count;
+      p = strchr (cmd, quote);
+      for (fpbs = p; fpbs != cmd && fpbs[-1] == '\\'; fpbs--);
+      bs_count = p - fpbs;
+      cmd = p - bs_count / 2;
+      if (bs_count % 2)
+	  strcpy (cmd - 1, p);
       else
 	{
-	  strcpy (cmd, cmd + 1);
+	  strcpy (cmd, p + 1);
 	  break;
 	}
     }
diff -r -up winsup-src-20000527-orig/cygwin/spawn.cc winsup-src-20000527-patched/cygwin/spawn.cc
--- winsup-src-20000527-orig/cygwin/spawn.cc	Wed Apr 26 07:20:04 2000
+++ winsup-src-20000527-patched/cygwin/spawn.cc	Mon May 29 02:06:32 2000
@@ -407,19 +407,23 @@ spawn_guts (HANDLE hToken, const char * 
 
       newargv0 = NULL;
       int len = strlen (a);
-      if (len != 0 && !(p = strpbrk (a, " \t\n\r\"")))
+      if (len != 0 && !strpbrk (a, " \t\n\r\""))
 	one_line.add (a, len);
       else
 	{
+	  char *fpbs;           /* The first preceding backslash */
 	  one_line.add ("\"", 1);
-	  for (; p; a = p, p = strchr (p, '"'))
+	  for (; (p = strchr (a, '"')); a = p + 1)
 	    {
-	      one_line.add (a, ++p - a);
-	      if (p[-1] == '"')
-		one_line.add ("\"", 1);
+	      one_line.add (a, p - a);
+	      for (fpbs = p; fpbs != a && fpbs[-1] == '\\'; fpbs--);
+	      one_line.add (fpbs, p - fpbs);
+	      one_line.add ("\\\"", 2);
 	    }
-	  if (*a)
-	    one_line.add (a);
+	  p = strchr (a, '\0');
+	  one_line.add (a, p - a);
+	  for (fpbs = p; fpbs[-1] == '\\'; fpbs--);
+	  one_line.add (fpbs, p - fpbs);
 	  one_line.add ("\"", 1);
 	}
       MALLOC_CHECK;

---------------------------------------------------
Get free personalized email at http://www.iname.com

--
Want to unsubscribe from this list?
Send a message to cygwin-unsubscribe@sourceware.cygnus.com

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

* Re: Command line arguments parsing problem
  2000-05-30 20:16 Command line arguments parsing problem bogus
@ 2000-05-31 10:46 ` MarketLogix
  2000-05-31 13:14   ` Chris Faylor
  0 siblings, 1 reply; 4+ messages in thread
From: MarketLogix @ 2000-05-31 10:46 UTC (permalink / raw)
  To: bogus; +Cc: cygwin

Yep,

argv[0] is surrounded by double quotes if you launch the executable
via mouse and NOT if launched from a shell.  This behavior was quietly
introduced between b19 and b20.

I'm thinking this may be related to your problem ...

Good luck.

bisk

Begin forwarded message:

I have many troubles with command line arguments parsing when I run a
non-cygwin program from bash. The problems occurs when I try to put
literal double quotation marks in arguments.
Here is a simple example that demonstrates the problem:

/tmp $ cat <<EOF > print_args.c
> #include <stdio.h>
>
> int
> main(int argc, char** argv) {
>   int i;
>   for(i = 1; i < argc; i++) {
>     printf("%d: %s\n", i, argv[i]);
>   }
>   exit(0);
> }
> EOF
/tmp $ gcc -o print_args_cygwin print_args.c
/tmp $ gcc -o print_args_nocygwin -mno-cygwin print_args.c
/tmp $ ./print_args_cygwin.exe '" "'
1: " "
/tmp $ ./print_args_nocygwin.exe '" "'
1: "
2: "

As you can see the non-cygwin program gets an inconsistent argv.

After some investigations, I discovered that a spawned windows
process doesn't get directly an array of disjointed arguments but a
command line it has to parse itself in order to build argv.
To build the command line that will be given to a sub-process, the
current cygwin implementation uses double quote marks to enclose
arguments while literal double quote marks are doubled.
For some unknown reasons, it appears that the non-cygwin programs
don't parse that syntax properly, but instead they seem to handle
correctly another syntax that uses backslashes to protect literal
double quote marks.
Eventually, I wrote the small patch below, so that cygwin uses the
backslash syntax. It seems to work fine, but as I'm a cygwin newbie,
it might actually be completly broken, and maybe there are good reasons
for using the double double quote marks syntax instead of the backslash
syntax. I'm waiting for your comments.

Regards,

Pierre Bogossian

PS: This patch doesn't fix the symmetrical problem: when a cygwin
program is called from a windows shell. But as I'm not using windows
shells anymore, that doesn't bother me that much ;-)

---

diff -r -up winsup-src-20000527-orig/cygwin/dcrt0.cc  
winsup-src-20000527-patched/cygwin/dcrt0.cc
--- winsup-src-20000527-orig/cygwin/dcrt0.cc	Mon May 22 05:55:16 2000
+++ winsup-src-20000527-patched/cygwin/dcrt0.cc	Mon May 29 04:19:34 2000
@@ -281,17 +281,21 @@ quoted (char *cmd, int winshell)
   /* When running as a child of a cygwin process, the quoted
      characters should have been placed here by spawn_guts, so
      we'll just pinch them out of the command string unless
-     they're quoted with a preceding \ */
+     they're quoted with an odd number of preceding \ */
   strcpy (cmd, cmd + 1);
-  while (*cmd)
+  while (1)
     {
-      if (*cmd != quote)
-	cmd++;
-      else if (cmd[1] == quote)
-	strcpy (cmd++, cmd + 1);
+      char *fpbs;           /* The first preceding backslash */
+      int bs_count;
+      p = strchr (cmd, quote);
+      for (fpbs = p; fpbs != cmd && fpbs[-1] == '\\'; fpbs--);
+      bs_count = p - fpbs;
+      cmd = p - bs_count / 2;
+      if (bs_count % 2)
+	  strcpy (cmd - 1, p);
       else
 	{
-	  strcpy (cmd, cmd + 1);
+	  strcpy (cmd, p + 1);
 	  break;
 	}
     }
diff -r -up winsup-src-20000527-orig/cygwin/spawn.cc  
winsup-src-20000527-patched/cygwin/spawn.cc
--- winsup-src-20000527-orig/cygwin/spawn.cc	Wed Apr 26 07:20:04 2000
+++ winsup-src-20000527-patched/cygwin/spawn.cc	Mon May 29 02:06:32 2000
@@ -407,19 +407,23 @@ spawn_guts (HANDLE hToken, const char *

       newargv0 = NULL;
       int len = strlen (a);
-      if (len != 0 && !(p = strpbrk (a, " \t\n\r\"")))
+      if (len != 0 && !strpbrk (a, " \t\n\r\""))
 	one_line.add (a, len);
       else
 	{
+	  char *fpbs;           /* The first preceding backslash */
 	  one_line.add ("\"", 1);
-	  for (; p; a = p, p = strchr (p, '"'))
+	  for (; (p = strchr (a, '"')); a = p + 1)
 	    {
-	      one_line.add (a, ++p - a);
-	      if (p[-1] == '"')
-		one_line.add ("\"", 1);
+	      one_line.add (a, p - a);
+	      for (fpbs = p; fpbs != a && fpbs[-1] == '\\'; fpbs--);
+	      one_line.add (fpbs, p - fpbs);
+	      one_line.add ("\\\"", 2);
 	    }
-	  if (*a)
-	    one_line.add (a);
+	  p = strchr (a, '\0');
+	  one_line.add (a, p - a);
+	  for (fpbs = p; fpbs[-1] == '\\'; fpbs--);
+	  one_line.add (fpbs, p - fpbs);
 	  one_line.add ("\"", 1);
 	}
       MALLOC_CHECK;

---------------------------------------------------
Get free personalized email at http://www.iname.com

--
Want to unsubscribe from this list?
Send a message to cygwin-unsubscribe@sourceware.cygnus.com



--
Want to unsubscribe from this list?
Send a message to cygwin-unsubscribe@sourceware.cygnus.com

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

* Re: Command line arguments parsing problem
  2000-05-31 10:46 ` MarketLogix
@ 2000-05-31 13:14   ` Chris Faylor
  0 siblings, 0 replies; 4+ messages in thread
From: Chris Faylor @ 2000-05-31 13:14 UTC (permalink / raw)
  To: cygwin

On Wed, May 31, 2000 at 10:45:03AM -0700, MarketLogix wrote:
>Yep,
>
>argv[0] is surrounded by double quotes if you launch the executable
>via mouse and NOT if launched from a shell.  This behavior was quietly
>introduced between b19 and b20.

Huh?  Are you somehow implying that cygwin knows when something has been
launched from a mouse?  I don't think so.

cgf

>I'm thinking this may be related to your problem ...
>
>Good luck.
>
>bisk
>
>Begin forwarded message:
>
>I have many troubles with command line arguments parsing when I run a
>non-cygwin program from bash. The problems occurs when I try to put
>literal double quotation marks in arguments.
>Here is a simple example that demonstrates the problem:
>
>/tmp $ cat <<EOF > print_args.c
>> #include <stdio.h>
>>
>> int
>> main(int argc, char** argv) {
>>   int i;
>>   for(i = 1; i < argc; i++) {
>>     printf("%d: %s\n", i, argv[i]);
>>   }
>>   exit(0);
>> }
>> EOF
>/tmp $ gcc -o print_args_cygwin print_args.c
>/tmp $ gcc -o print_args_nocygwin -mno-cygwin print_args.c
>/tmp $ ./print_args_cygwin.exe '" "'
>1: " "
>/tmp $ ./print_args_nocygwin.exe '" "'
>1: "
>2: "
>
>As you can see the non-cygwin program gets an inconsistent argv.
>
>After some investigations, I discovered that a spawned windows
>process doesn't get directly an array of disjointed arguments but a
>command line it has to parse itself in order to build argv.
>To build the command line that will be given to a sub-process, the
>current cygwin implementation uses double quote marks to enclose
>arguments while literal double quote marks are doubled.
>For some unknown reasons, it appears that the non-cygwin programs
>don't parse that syntax properly, but instead they seem to handle
>correctly another syntax that uses backslashes to protect literal
>double quote marks.
>Eventually, I wrote the small patch below, so that cygwin uses the
>backslash syntax. It seems to work fine, but as I'm a cygwin newbie,
>it might actually be completly broken, and maybe there are good reasons
>for using the double double quote marks syntax instead of the backslash
>syntax. I'm waiting for your comments.
>
>Regards,
>
>Pierre Bogossian
>
>PS: This patch doesn't fix the symmetrical problem: when a cygwin
>program is called from a windows shell. But as I'm not using windows
>shells anymore, that doesn't bother me that much ;-)
>
>---
>
>diff -r -up winsup-src-20000527-orig/cygwin/dcrt0.cc  
>winsup-src-20000527-patched/cygwin/dcrt0.cc
>--- winsup-src-20000527-orig/cygwin/dcrt0.cc	Mon May 22 05:55:16 2000
>+++ winsup-src-20000527-patched/cygwin/dcrt0.cc	Mon May 29 04:19:34 2000
>@@ -281,17 +281,21 @@ quoted (char *cmd, int winshell)
>   /* When running as a child of a cygwin process, the quoted
>      characters should have been placed here by spawn_guts, so
>      we'll just pinch them out of the command string unless
>-     they're quoted with a preceding \ */
>+     they're quoted with an odd number of preceding \ */
>   strcpy (cmd, cmd + 1);
>-  while (*cmd)
>+  while (1)
>     {
>-      if (*cmd != quote)
>-	cmd++;
>-      else if (cmd[1] == quote)
>-	strcpy (cmd++, cmd + 1);
>+      char *fpbs;           /* The first preceding backslash */
>+      int bs_count;
>+      p = strchr (cmd, quote);
>+      for (fpbs = p; fpbs != cmd && fpbs[-1] == '\\'; fpbs--);
>+      bs_count = p - fpbs;
>+      cmd = p - bs_count / 2;
>+      if (bs_count % 2)
>+	  strcpy (cmd - 1, p);
>       else
> 	{
>-	  strcpy (cmd, cmd + 1);
>+	  strcpy (cmd, p + 1);
> 	  break;
> 	}
>     }
>diff -r -up winsup-src-20000527-orig/cygwin/spawn.cc  
>winsup-src-20000527-patched/cygwin/spawn.cc
>--- winsup-src-20000527-orig/cygwin/spawn.cc	Wed Apr 26 07:20:04 2000
>+++ winsup-src-20000527-patched/cygwin/spawn.cc	Mon May 29 02:06:32 2000
>@@ -407,19 +407,23 @@ spawn_guts (HANDLE hToken, const char *
>
>       newargv0 = NULL;
>       int len = strlen (a);
>-      if (len != 0 && !(p = strpbrk (a, " \t\n\r\"")))
>+      if (len != 0 && !strpbrk (a, " \t\n\r\""))
> 	one_line.add (a, len);
>       else
> 	{
>+	  char *fpbs;           /* The first preceding backslash */
> 	  one_line.add ("\"", 1);
>-	  for (; p; a = p, p = strchr (p, '"'))
>+	  for (; (p = strchr (a, '"')); a = p + 1)
> 	    {
>-	      one_line.add (a, ++p - a);
>-	      if (p[-1] == '"')
>-		one_line.add ("\"", 1);
>+	      one_line.add (a, p - a);
>+	      for (fpbs = p; fpbs != a && fpbs[-1] == '\\'; fpbs--);
>+	      one_line.add (fpbs, p - fpbs);
>+	      one_line.add ("\\\"", 2);
> 	    }
>-	  if (*a)
>-	    one_line.add (a);
>+	  p = strchr (a, '\0');
>+	  one_line.add (a, p - a);
>+	  for (fpbs = p; fpbs[-1] == '\\'; fpbs--);
>+	  one_line.add (fpbs, p - fpbs);
> 	  one_line.add ("\"", 1);
> 	}
>       MALLOC_CHECK;

--
Want to unsubscribe from this list?
Send a message to cygwin-unsubscribe@sourceware.cygnus.com

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

* Re: Command line arguments parsing problem
@ 2000-05-31 17:41 bogus
  0 siblings, 0 replies; 4+ messages in thread
From: bogus @ 2000-05-31 17:41 UTC (permalink / raw)
  To: mlx; +Cc: cygwin

>argv[0] is surrounded by double quotes if you launch the executable
>via mouse and NOT if launched from a shell.  This behavior was quietly
>introduced between b19 and b20.
>
>I'm thinking this may be related to your problem ...

No, this doesn't seem to be related. Actually, I think that the cause
of the problem is well understood (read my previous mail).
My question was rather "Is the patch I submitted the right way to fix
it or did I miss something ?"

Pierre Bogossian

---------------------------------------------------
Get free personalized email at http://www.iname.com

--
Want to unsubscribe from this list?
Send a message to cygwin-unsubscribe@sourceware.cygnus.com

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

end of thread, other threads:[~2000-05-31 17:41 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2000-05-30 20:16 Command line arguments parsing problem bogus
2000-05-31 10:46 ` MarketLogix
2000-05-31 13:14   ` Chris Faylor
2000-05-31 17:41 bogus

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).