[run] branch master, updated. 1e1c404112e13d34f16dfaeff7343f1daafc731b

gratz@sourceware.org gratz@sourceware.org
Sat Aug 22 07:45:00 GMT 2015




https://sourceware.org/git/gitweb.cgi?p=cygwin-run.git;h=1e1c404112e13d34f16dfaeff7343f1daafc731b

commit 1e1c404112e13d34f16dfaeff7343f1daafc731b
Author: Achim Gratz <Stromeko@Stromeko.DE>
Date:   Sat Aug 22 09:39:53 2015 +0200

    release 1.3.4

https://sourceware.org/git/gitweb.cgi?p=cygwin-run.git;h=4470ca51d0e12d44124b71c8c1cf479d6bf0e663

commit 4470ca51d0e12d44124b71c8c1cf479d6bf0e663
Author: Achim Gratz <Stromeko@Stromeko.DE>
Date:   Thu Aug 13 21:23:45 2015 +0200

    When quoting, do not simply skip empty arguments

https://sourceware.org/git/gitweb.cgi?p=cygwin-run.git;h=adb8378775705fcc99aa29e5a8b6970349d37656

commit adb8378775705fcc99aa29e5a8b6970349d37656
Author: Achim Gratz <Stromeko@Stromeko.DE>
Date:   Thu Aug 13 21:08:57 2015 +0200

    Hoist char* t out of loop and initialize NULL
    
    	* src/run.c (file_exists_multi): Hoist char* t out of loop and
    	initialize NULL.  Remove redundant truncation of fullname.

https://sourceware.org/git/gitweb.cgi?p=cygwin-run.git;h=2fb8fd2461111d66d4efbb8bd6b1e022f0006cd5

commit 2fb8fd2461111d66d4efbb8bd6b1e022f0006cd5
Author: Achim Gratz <Stromeko@Stromeko.DE>
Date:   Thu Aug 13 21:04:54 2015 +0200

    Replace stricmp with strcasecmp throughout
    
    	* src/run.c (xemacs_special): Replace stricmp with strcasecmp throughout.
    	* src/util.c (run2_ends_with): Ditto.
    
    Whitespace cleanup in ChangeLog.

https://sourceware.org/git/gitweb.cgi?p=cygwin-run.git;h=a28455a88187d1c22f97db1627e530c8d082b680

commit a28455a88187d1c22f97db1627e530c8d082b680
Author: Achim Gratz <Stromeko@Stromeko.DE>
Date:   Thu Aug 13 21:01:41 2015 +0200

    Implement -wait/--wait and -quote/--quote as valid long options
    
    	* src/run.c (parse_args): Implement -wait/--wait and
    	-quote/--quote as valid long options, we prefer the double-dash
    	variant.
    	* src/run.1.in: All long options are preferedly using leading
    	double dashes.  Document the fact that single slashes work on two
    	of them for backwards compatibility.

https://sourceware.org/git/gitweb.cgi?p=cygwin-run.git;h=8d6f51656f17fe0a9b54df0919ac2826b35fa0de

commit 8d6f51656f17fe0a9b54df0919ac2826b35fa0de
Author: Achim Gratz <Stromeko@Stromeko.DE>
Date:   Sat Sep 6 15:29:15 2014 +0200

    add "-quote" option and refactor quoting to use run2_quote_strdup

https://sourceware.org/git/gitweb.cgi?p=cygwin-run.git;h=8716ae80067a6bbde2a50da58a42d0f3c22c325e

commit 8716ae80067a6bbde2a50da58a42d0f3c22c325e
Author: Achim Gratz <Stromeko@Stromeko.DE>
Date:   Sat Sep 6 14:19:48 2014 +0200

    refactor options removal during argument parsing

https://sourceware.org/git/gitweb.cgi?p=cygwin-run.git;h=79a45ad1c625dae7f32f792169d9412ee9772976

commit 79a45ad1c625dae7f32f792169d9412ee9772976
Author: Achim Gratz <Stromeko@Stromeko.DE>
Date:   Sat Sep 6 13:58:20 2014 +0200

    revert indiscriminate argument quoting since some programs don't expect quoted options

https://sourceware.org/git/gitweb.cgi?p=cygwin-run.git;h=9dcabef66716f47b8853596144a805e352de5886

commit 9dcabef66716f47b8853596144a805e352de5886
Author: Achim Gratz <Stromeko@Stromeko.DE>
Date:   Mon Jun 9 20:02:12 2014 +0200

    quote args and account for NULL argv list terminator, correct some occurences of error to errorMsg


Diff:
---
 ChangeLog    |   73 +++++++++++++++++++++++++---
 configure.ac |   10 ++--
 src/run.1.in |   26 ++++++++--
 src/run.c    |  153 ++++++++++++++++++++-------------------------------------
 src/util.c   |   37 +++++++++++++-
 src/util.h   |    1 +
 6 files changed, 184 insertions(+), 116 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index a6f55ca..5d69344 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,62 @@
+2015-08-22  Achim Gratz  <Stromeko@NexGo.DE>
+
+	* configure.ac: Bump version number.  Add strcasecmp to
+	AC_CHECK_FUNCS.
+
+2015-08-13  Achim Gratz  <Stromeko@NexGo.DE>
+
+	* src/util.c (run2_quote_strdup): When quoting, do not simply skip
+	empty arguments but return '""'.
+
+2015-08-13  Achim Gratz  <Stromeko@NexGo.DE>
+
+	* src/run.c (file_exists_multi): Hoist char* t out of loop and
+	initialize NULL.  Remove redundant truncation of fullname.
+
+2015-08-13  Achim Gratz  <Stromeko@NexGo.DE>
+
+	* src/run.c (xemacs_special): Replace stricmp with strcasecmp throughout.
+	* src/util.c (run2_ends_with): Ditto.
+
+2015-08-13  Achim Gratz <Stromeko@NexGo.DE>
+
+	* src/run.c (parse_args): Implement -wait/--wait and
+	-quote/--quote as valid long options, we prefer the double-dash
+	variant.
+	* src/run.1.in: All long options are preferedly using leading
+	double dashes.  Document the fact that single slashes work on two
+	of them for backwards compatibility.
+
+2014-09-06  Achim Gratz <Stromeko@Stromeko.DE>
+
+	* configure.ac: Bump version number.  Correct some type, header
+	and function checks.
+	* src/run.c: Add "-quote" option.  Use run2_quote_strdup function
+	to (maybe) quote the input string.
+	* src/util.c: New function run2_quote_strdup.  If the quote
+	argument is false, then just copy the input string via
+	run2_strdup.  Otherwise, check if the input string needs quoting.
+	If yes, then surround the string with double quotes and quote all
+	embedded double quotes and backslahses with a backslash.
+	* src/util.h: New function run2_quote_strdup.
+
+2014-09-06  Achim Gratz <Stromeko@Stromeko.DE>
+
+	* src/run.c: Revert indiscriminate argument quoting.  This also
+	quotes options and apparently some programs process options before
+	quote removal.
+
+2014-06-09  Achim Gratz <Stromeko@Stromeko.DE>
+
+	* configure.ac: Bump version number.
+	* src/run.c: Correct some calls to error, obviously these were
+	meant to call errorMsg.
+
+2013-11-30  Max Polk  <maxpolk@gmail.com>
+
+	* src/run.c: account for NULL argv list terminator.  Surround
+	arguments with double quotes in case of space in original arg.
+
 2013-07-24  Charles Wilson  <cygwin@cwilson.fastmail.fm>
 
 	Release 1.3.0. Massive refactoring.
@@ -51,7 +110,7 @@
 
 	Support cygwin64, mingw64
 	* configure.ac: Detect cygwin64 and mingw64. Detect
-	signature of _spawnv() and spawnv(). Update to 
+	signature of _spawnv() and spawnv(). Update to
 	recent autotools.
 	* src/Makefile.am: Use correct entrypoint for 64bit
 	platforms.
@@ -210,7 +269,7 @@
 	* build-aux/.cvsignore: New.
 	* m4/.cvsignore: New.
 
-2006-05-22  Charles Wilson  <cygwin@cwilson.fastmail.fm> 
+2006-05-22  Charles Wilson  <cygwin@cwilson.fastmail.fm>
 
 	Release 1.1.10
 
@@ -317,7 +376,7 @@
 	release are still present, because they were added right
 	back in run-1.1.5...
 
-	Finally, ALL of these changes, from this point down to 
+	Finally, ALL of these changes, from this point down to
 	the release of version 1.1.4 below, are one single checkin
 	in the repository, because we no longer have access to
 	the development repository of the time.
@@ -342,7 +401,7 @@
 2004-10-06  Alexander Gottwald  <ago at freedesktop dot org>
 
 	* run.c: Added ability to expand PATH variable with
-	-p <dir> parameter 
+	-p <dir> parameter
 
 2004-03-11    <harold@codeweavers.com>
 
@@ -379,7 +438,7 @@ Version 1.1.2 -  5-Dec-98 (NOT RELEASED)
 	  are called on paths/pathlists that are already in posix format
 	  they return garbage in B19. So don't call them when you don't
 	  have to.
-	- CYGWIN: added #defines to enable building under both B19 and 
+	- CYGWIN: added #defines to enable building under both B19 and
 	  B20 without modifying the source code. UNTESTED under B20.
 
 Version 1.1.1 - 30-Nov-98 (NOT RELEASED)
@@ -392,12 +451,12 @@ Version 1.1.0 - 18-Nov-98 (NOT RELEASED)
 --------------------------
 	- added ability to search PATH for the target
 	- added ability to specify explicit path information for
-	  the target, which removed requirement that run.exe and 
+	  the target, which removed requirement that run.exe and
 	  the target be in the same directory
 	- added "simple" mode of operation, where run.exe is
 	  renamed to runXXXXXX.exe, to run target XXXXXX
 	- SHOWSTOPPER: cygwin version gets confused if '\\' character
-	  appears in the argument list 
+	  appears in the argument list
 
 Version 1.0.0 - 29-Sept-98
 --------------------------
diff --git a/configure.ac b/configure.ac
index 15e0cb7..96cb8d1 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2,7 +2,7 @@ dnl Process this file with autoconf to produce a configure script.
 
 dnl Auto* initialization
 AC_PREREQ([2.69])
-AC_INIT([run], [1.3.0], [cygwin@cygwin.com])
+AC_INIT([run], [1.3.4], [cygwin@cygwin.com])
 AC_CONFIG_SRCDIR(src/run.c)
 AC_CONFIG_AUX_DIR([build-aux])
 AC_CONFIG_MACRO_DIR([m4])
@@ -87,19 +87,21 @@ AM_PROG_AR
 AC_PROG_INSTALL
 
 # checks for header files
-AC_CHECK_HEADERS([locale.h malloc.h stdlib.h math.h string.h assert.h pwd.h])
+AC_CHECK_HEADERS([float.h locale.h malloc.h stdlib.h string.h assert.h pwd.h unistd.h])
 AC_CHECK_HEADERS([getopt.h sys/cygwin.h windows.h])
 
 # Checks for typedefs, structures, and compiler characteristics.
 AC_C_CONST
 AC_TYPE_SIZE_T
+AC_TYPE_SSIZE_T
 
 # Checks for library functions.
+AC_FUNC_LSTAT_FOLLOWS_SLASHED_SYMLINK
 AC_FUNC_MALLOC
+AC_FUNC_REALLOC
 AC_FUNC_STRTOD
 AC_FUNC_VPRINTF
-AC_CHECK_FUNC([setenv])
-AC_CHECK_FUNCS([clock_gettime floor setlocale strdup setenv])
+AC_CHECK_FUNCS([getcwd memset putenv setenv setlocale strcasecmp strchr strcspn strdup strerror strrchr strtol])
 AC_CHECK_FUNC([getopt_long], [], [replace_getopt=yes])
 AM_CONDITIONAL([REPLACE_GETOPT], [test "$replace_getopt" = yes])
 if test "$replace_getopt" = yes; then
diff --git a/src/run.1.in b/src/run.1.in
index ebe9c3b..28b4c7d 100644
--- a/src/run.1.in
+++ b/src/run.1.in
@@ -1,13 +1,13 @@
-.TH RUN 1 November\ 2005 Version\ @VERSION@ run\ @VERSION@
+.TH RUN 1 September\ 2014 Version\ @VERSION@ run\ @VERSION@
 .SH NAME
 run - start programs with hidden console window
 
 .SH SYNOPSIS
 .B run
-[ -p path ] command [ -wait ] arguments
+[ -p path ] command [ --wait ] [ --quote ] arguments
 
 .B runcommand
-[ -p path ] [ -wait ] arguments
+[ -p path ] [ --wait ] [ --quote ] arguments
 
 .SH DESCRIPTION
 Windows programs are either GUI programs or console programs. When  started
@@ -26,17 +26,35 @@ you can add
 to the PATH environment variable.
 
 Issuing 
-.B -wait
+.B --wait
 as first program  argument will make 
 .I run 
 wait for program completition, otherwise it returns immediately.
 
+The
+.B --quote
+option enables automatic quoting of arguments with embedded
+whitespace, double quotes or backslashes for consumption by the
+standard Microsoft startup code or compatible implementations.  If you
+do not use this option,
+.I run
+assumes that the arguments are already correctly quoted for the
+consumer and simply concatenates them separated by single spaces.
+
 The second variant is for  creating wrappers. If the executable is named
 .B runcommand 
 (eg runemacs), 
 .I run
 will try  to start the program (eg emacs).
 
+.SH NOTES
+
+For backwards compatibility, the long options
+.B -wait
+and
+.B -quote
+can be issued with a single leading dash.
+
 .SH EXAMPLES
 run -p /usr/X11R6/bin xterm
 
diff --git a/src/run.c b/src/run.c
index ca3a75c..0064844 100644
--- a/src/run.c
+++ b/src/run.c
@@ -84,6 +84,7 @@ int opt_loglevel = RUN2_DEFAULT_LOG_SILENT_LEVEL;
 int opt_loglevel = RUN2_DEFAULT_LOG_LEVEL;
 #endif
 int opt_wait = 0;
+int opt_quote = 0;
 int argv_is_malloc = 0;
 
 static void
@@ -93,6 +94,7 @@ dumpOpts(void)
   debugMsg(1, "opt_nogui   : %d", opt_nogui);
   debugMsg(1, "opt_notty   : %d", opt_notty);
   debugMsg(1, "opt_wait    : %d", opt_wait);
+  debugMsg(1, "opt_quote   : %d", opt_quote);
 }
 
 char buffer[1024];
@@ -150,11 +152,13 @@ WinMain (HINSTANCE hSelf, HINSTANCE hPrev, LPSTR cmdline, int nShow)
       return 1;
     }
 
-  /* protect embedded spaces in bufArg0 */
-  strcpy(fullCmdLine, "\"");
-  strcat(fullCmdLine, bufArg0);
-  strcat(fullCmdLine, "\" ");
-  strcat(fullCmdLine, cmdline);
+  {
+    /* quote special chars in bufArg0 */
+    char * quoteArg0 = run2_quote_strdup (bufArg0, 1);
+    strcat(fullCmdLine, quoteArg0);
+    strcat(fullCmdLine, cmdline);
+    free (quoteArg0);
+  }
   free (bufArg0);
 
   debugMsg(1, "new cmdline = %s", fullCmdLine);
@@ -252,7 +256,8 @@ realMain(int argc, char* argv[])
       newargv = run2_dupargv (argv);
       /* discard newargv[0] and shift up */
       free (newargv[0]);
-      for (newargc = 1; newargc < argc; newargc++)
+      /* Account for NULL array terminator */
+      for (newargc = 1; newargc <= argc; newargc++)
          newargv[newargc-1] = newargv[newargc];
       newargc = argc - 1;
 
@@ -391,13 +396,13 @@ xemacs_special(char* exec)
    char tmp[MAX_PATH + FILENAME_MAX + 100];
    strcpy(exec2,exec);
    /* this depends on short-circuit evaluation */
-   if ( ((p = strrchr(exec2,'\\')) && stricmp(p,"\\xemacs") == 0) ||
-        ((p = strrchr(exec2,'/')) && stricmp(p,"/xemacs") == 0) ||
-        ((p = strrchr(exec2,'\\')) && stricmp(p,"\\xemacs.exe") == 0) ||
-        ((p = strrchr(exec2,'/')) && stricmp(p,"/xemacs.exe") == 0) )
+   if ( ((p = strrchr(exec2,'\\')) && strcasecmp(p,"\\xemacs") == 0) ||
+        ((p = strrchr(exec2,'/')) && strcasecmp(p,"/xemacs") == 0) ||
+        ((p = strrchr(exec2,'\\')) && strcasecmp(p,"\\xemacs.exe") == 0) ||
+        ((p = strrchr(exec2,'/')) && strcasecmp(p,"/xemacs.exe") == 0) )
    {
-      if ( ((p2 = strrchr(p, '\\')) && stricmp(p2, "\\bin") == 0) ||
-           ((p2 = strrchr(p, '/')) && stricmp(p2, "/bin") == 0) )
+      if ( ((p2 = strrchr(p, '\\')) && strcasecmp(p2, "\\bin") == 0) ||
+           ((p2 = strrchr(p, '/')) && strcasecmp(p2, "/bin") == 0) )
       {
          *p2 = '\0';
 #if defined(__CYGWIN__)
@@ -413,6 +418,16 @@ xemacs_special(char* exec)
    }
 }
 
+static void
+remove_args(int *argc, char* argv[], int i)
+{
+  int j;
+  /* remove argv[i] from argv array */
+  if (argv_is_malloc) free (argv[i]);
+  for (j = i+1; j < *argc; j++)
+    argv[i++] = argv[j];
+  argv[--*argc] = NULL;
+}
 static int
 parse_args(int *argc, char* argv[])
 {
@@ -448,90 +463,40 @@ parse_args(int *argc, char* argv[])
          }
          add_path (next);
 
-         /* remove -p and it argument from argv */
-         if (argv_is_malloc)
-         {
-            free (argv[i]);
-            free (argv[i+1]);
-         }
-         for (j = i; j < *argc-2; j++)
-            argv[j] = argv[j+2];
-         argv[*argc-1] = '\0';
-         *argc -= 2;
-
-         /*
-          * since argv[i] now points to a new argument,
-          * reset i for the next pass
-          */
-         i--;
+         /* remove -p and its argument from argv */
+	 remove_args(argc, argv, i);
+	 remove_args(argc, argv, i--);
       }
-      else if (strcmp(argv[i],"-wait") == 0)
+      else if ((strcmp(argv[i],"--wait") == 0) ||
+	       (strcmp(argv[i],"-wait")  == 0))
       {
          opt_wait = 1;
-         /* remove argv[i] from argv array */
-         if (argv_is_malloc) free (argv[i]);
-         for (j = i; j < *argc-1; j++)
-           argv[j] = argv[j+1];
-         argv[*argc-1] = NULL;
-         *argc -= 1;
-
-         /*
-          * since argv[i] now points to a new argument,
-          * reset i for the next pass
-          */
-         i--;
+	 remove_args(argc, argv, i--);
+      }
+	       else if ((strcmp(argv[i],"--quote") == 0) ||
+			(strcmp(argv[i],"-quote")  == 0))
+      {
+         opt_quote = 1;
+	 remove_args(argc, argv, i--);
       }
 #if (ENABLE_GUI == 1)
       else if (strcmp(argv[i],"--run-nogui") == 0)
       {
          opt_nogui = 1;
-         /* remove argv[i] from argv array */
-         if (argv_is_malloc) free (argv[i]);
-         for (j = i; j < *argc-1; j++)
-           argv[j] = argv[j+1];
-         argv[*argc-1] = NULL;
-         *argc -= 1;
-
-         /*
-          * since argv[i] now points to a new argument,
-          * reset i for the next pass
-          */
-         i--;
+	 remove_args(argc, argv, i--);
       }
 #endif
 #if (ENABLE_TTY == 1)
       else if (strcmp(argv[i],"--run-notty") == 0)
       {
          opt_notty = 1;
-         /* remove argv[i] from argv array */
-         if (argv_is_malloc) free (argv[i]);
-         for (j = i; j < *argc-1; j++)
-           argv[j] = argv[j+1];
-         argv[*argc-1] = NULL;
-         *argc -= 1;
-
-         /*
-          * since argv[i] now points to a new argument,
-          * reset i for the next pass
-          */
-         i--;
+	 remove_args(argc, argv, i--);
       }
 #endif
       else if (strcmp(argv[i],"--run-verbose") == 0)
       {
          opt_loglevel = RUN2_DEFAULT_LOG_VERBOSE_LEVEL;
-         /* remove argv[i] from argv array */
-         if (argv_is_malloc) free (argv[i]);
-         for (j = i; j < *argc-1; j++)
-           argv[j] = argv[j+1];
-         argv[*argc-1] = NULL;
-         *argc -= 1;
-
-         /*
-          * since argv[i] now points to a new argument,
-          * reset i for the next pass
-          */
-         i--;
+	 remove_args(argc, argv, i--);
       }
       else if (strncmp(argv[i],"--run-debug=", 12) == 0)
       {
@@ -551,18 +516,7 @@ parse_args(int *argc, char* argv[])
          {
             opt_loglevel = RUN2_LOG_DEBUG;
          }
-         /* remove argv[i] from argv array */
-         if (argv_is_malloc) free (argv[i]);
-         for (j = i; j < *argc-1; j++)
-           argv[j] = argv[j+1];
-         argv[*argc-1] = NULL;
-         *argc -= 1;
-
-         /*
-          * since argv[i] now points to a new argument,
-          * reset i for the next pass
-          */
-         i--;
+	 remove_args(argc, argv, i--);
       }
    }
    return 0;
@@ -576,15 +530,17 @@ build_cmdline(char* new_cmdline, char* exec, int argc, char* argv[])
 
    char_cnt = strlen(exec);
    for (i = 1; i < argc; i++)
-      char_cnt += strlen(argv[i]);
+     char_cnt += strlen(argv[i]);
    if (char_cnt > MAX_ARGS*MAX_PATH) /* then we ran out of room */
       run2_error(EXIT_FAILURE, 0, "command line too long -\n%s",new_cmdline);
 
    strcpy(new_cmdline,exec);
    for (i = 1; i < argc; i++)
    {
-      strcat(new_cmdline," ");
-      strcat(new_cmdline,argv[i]);
+     char* quoteArgvi = run2_quote_strdup (argv[i], opt_quote);
+     strcat(new_cmdline, " ");
+     strcat(new_cmdline, quoteArgvi);
+     free (quoteArgvi);
    }
 }
 
@@ -870,22 +826,22 @@ add_path_cygwin(const char *str)
         if (lasterror == ERROR_ENVVAR_NOT_FOUND)
         {
             if (!SetEnvironmentVariable("PATH", wstr))
-                error("SetEnvironmentVariable failed: 0x%x", GetLastError());
+                errorMsg("SetEnvironmentVariable failed: 0x%x", GetLastError());
         }
-        error("GetEnvironmentVariable failed: 0x%x", lasterror);
+        errorMsg("GetEnvironmentVariable failed: 0x%x", lasterror);
     }
     buffer = malloc(envsize + slen + 2);
     if (buffer == NULL)
-        error("internal error - out of memory");
+        errorMsg("internal error - out of memory");
 
     if (!GetEnvironmentVariable("PATH", buffer, envsize))
-        error("GetEnvironmentVariable failed: 0x%x", GetLastError());
+        errorMsg("GetEnvironmentVariable failed: 0x%x", GetLastError());
 
     strcat(buffer, ";");
     strcat(buffer, wstr);
 
     if (!SetEnvironmentVariable("PATH", buffer))
-        error("SetEnvironmentVariable failed: 0x%x", GetLastError());
+        errorMsg("SetEnvironmentVariable failed: 0x%x", GetLastError());
     free(buffer);
 }
 
@@ -919,10 +875,10 @@ file_exists_multi(char* fullname, const char* path,
     char tryName[MAX_PATH + FILENAME_MAX];
     int i = 0;
     int retval = FALSE;
+    char* t = NULL;
     fullname[0] = '\0';
     for (i = 0; i < extcnt; i++)
     {
-        char* t;
         strcpy(tryName,name_noext);
         strcat(tryName,exts[i]);
         if ((run2_fileExists(&t, path, tryName) == TRUE) && t && *t)
@@ -937,7 +893,6 @@ file_exists_multi(char* fullname, const char* path,
           free(t);
           t = NULL;
         }
-        fullname[0] = '\0';
     }
     return retval;
 }
diff --git a/src/util.c b/src/util.c
index 31249c0..acfc4a5 100755
--- a/src/util.c
+++ b/src/util.c
@@ -125,7 +125,7 @@ run2_ends_with(const char* s1, const char* s2)
   len1 = strlen(s1);
   len2 = strlen(s2);
   if (len1 - len2 >= 0)
-    if (stricmp(&(s1[len1-len2]),s2) == 0)
+    if (strcasecmp(&(s1[len1-len2]),s2) == 0)
       retval = 1;
   return retval;
 }
@@ -136,7 +136,7 @@ run2_strip_exe(char* s)
   size_t slen = strlen(s);
   if ((slen > 4) && /* long enough to have .exe extension */
     /* second part not evaluated (short circuit) if exec_arg too short */
-    (stricmp(&(s[slen-4]),".exe") == 0))
+    (strcasecmp(&(s[slen-4]),".exe") == 0))
   s[slen-4] = '\0';
 }
 
@@ -523,6 +523,39 @@ run2_strdup (const char *s)
   return d;
 }
 
+char*
+run2_quote_strdup (const char *s, int quote)
+{
+  size_t len = strlen (s);
+  if (len == 0)
+    return "\"\"";
+  if (quote && (len > strcspn (s, " \t\v\"\\")))
+    {
+      size_t i, j = 0;
+      char * d = (char *) run2_malloc (2*len + 3);
+      d[j++] = '"';
+      for (i=0; i<len; i++)
+	{
+	  switch (s[i]) {
+	  case '\\':
+	    d[j++] = '\\';
+	    d[j++] = '\\';
+	    break;
+	  case '"':
+	    d[j++] = '\\';
+	    d[j++] = '"';
+	    break;
+	  default:
+	    d[j++] = s[i];
+	  }
+	}
+      d[j++] = '"';
+      d[j++] = '\0';
+      return d;
+    }
+  return run2_strdup (s);
+}
+
 char *
 run2_extend_str (const char *orig_value, const char *add, int to_end)
 {
diff --git a/src/util.h b/src/util.h
index 7a2799e..414aad7 100755
--- a/src/util.h
+++ b/src/util.h
@@ -89,6 +89,7 @@ void run2_error (int status, int errnum, const char *message, ...);
 void *run2_malloc  (size_t);
 void *run2_realloc (void *, size_t);
 char *run2_strdup  (const char *arg);
+char *run2_quote_strdup  (const char *arg, int quote);
 char *run2_extend_str (const char *orig_value, const char *add, int to_end);
 int run2_strtol(char *arg, long* value);
 char *run2_get_homedir (const char *user);



More information about the Cygwin-apps-cvs mailing list