This is the mail archive of the cygwin@sourceware.cygnus.com mailing list for the Cygwin project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Re: Command line arguments parsing problem


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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]