This is the mail archive of the cygwin 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]
Other format: [Raw text]

Re: [ANNOUNCEMENT] Updated: run-1.1.11-1


Corinna Vinschen wrote:

> Oh well.  The above shortcut as well as your startxwin.bat script don't
> work on W7.  Only a shortcut like this
> 
>   C:\cygwin-1.7\bin\run.exe emacs-X11 --display=127.0.0.1:0.0
> 
> works and allows to start emacs.

So, here's another approach that seems to work for me, based on the
earlier conversation about treating GUI apps specially.  It's not nearly
as clean as Corinna's, but maybe it will work also on W7. No ChangeLog
yet...

Apply to current CVS.

--
Chuck

Index: src/run.c
===================================================================
RCS file: /cvs/cygwin-apps/run/src/run.c,v
retrieving revision 1.8
diff -u -p -r1.8 run.c
--- src/run.c	16 Aug 2009 03:26:42 -0000	1.8
+++ src/run.c	17 Aug 2009 15:35:54 -0000
@@ -45,6 +45,7 @@
 #include <stdlib.h>
 #include <stdio.h>
 #include <stdarg.h>
+#include <process.h>
 
 #include "run.h"
 
@@ -63,6 +64,9 @@ WinMainCRTStartup() { mainCRTStartup(); 
 DWORD os_version;
 char buffer[1024];
 
+static BOOL target_is_gui(const char* target_path);
+static void setup_win_environ(void);
+
 int WINAPI
 WinMain (HINSTANCE hSelf, HINSTANCE hPrev, LPSTR cmdline, int nShow)
 {
@@ -165,11 +169,61 @@ WinMain (HINSTANCE hSelf, HINSTANCE hPre
    Trace(("exec\t%s\nexecname\t%s\nexecpath\t%s\n",
          exec,execname,execpath));
 
-   wait_for_child = build_cmdline(cmdline2,exec,argc,argv);
+   wait_for_child = build_cmdline(cmdline2,exec,&argc,argv);
    Trace((cmdline2));
 
    xemacs_special(exec);
-   ret_code = start_child(cmdline2,wait_for_child);
+   if (target_is_gui (exec))
+     {
+       /* much simpler if target is gui, because we don't
+        * actually need to worry about consoles, stdio
+        * handles, etc.  If -wait, then delegate to _spawnv,
+        * since we have the argv array. However, because
+        * _spawnv (_P_NOWAIT) doesn't work reliably on
+        * cygwin, use a lobotomized version of CreateProcess
+        * (but still don't worry about handles or consoles).
+        */
+       setup_win_environ();
+       if (wait_for_child)
+         {
+           Trace(("gui wait for child: %s", exec));
+           /* ret_code is the child exit status for P_WAIT */
+           ret_code = _spawnv (_P_WAIT, exec, argv);
+           if (ret_code < 0)
+             error("could not start %s", exec);
+           return (int)ret_code;
+         }
+       else
+         {
+           STARTUPINFO start;
+           PROCESS_INFORMATION child;
+           ZeroMemory( &child, sizeof(PROCESS_INFORMATION) );
+           ZeroMemory (&start, sizeof (STARTUPINFO));
+           start.cb = sizeof (STARTUPINFO);
+           Trace(("Launch GUI target, async (cygwin-1.5): %s", cmdline2));
+           ret_code = CreateProcess (NULL,
+               cmdline2,/* command line                        */
+               NULL,    /* process security attributes         */
+               NULL,    /* primary thread security attributes  */
+               FALSE,   /* handles are NOT inherited,          */
+               0,       /* creation flags                      */
+               NULL,    /* use parent's environment            */
+               NULL,    /* use parent's current directory      */
+               &start,  /* STARTUPINFO pointer                 */
+               &child); /* receives PROCESS_INFORMATION        */
+           if (ret_code == 0)
+             {
+               Trace(("getlasterror: %d\n", GetLastError()));
+               error("could not start %s", exec);
+             }
+           return 0;
+         }
+     }
+   else
+     {
+       Trace(("Launch non-GUI target"));
+       ret_code = start_child(exec, cmdline2,wait_for_child);
+     }
    if (compact_invocation)
       for (i = 1; i < argc; i++) /* argv[0] was not malloc'ed */
          free(argv[i]);
@@ -179,6 +233,22 @@ WinMain (HINSTANCE hSelf, HINSTANCE hPre
    return (int) ret_code;
 }
 
+static BOOL target_is_gui(const char* target_path)
+{
+  char p, e;
+  DWORD_PTR d =
+  SHGetFileInfoA(target_path,    /* LPCSTR pszPath         */
+                 0,              /* DWORD dwFileAttributes */
+                 NULL,           /* SHFILEINFO *psfi       */
+                 0,              /* UINT cbFileInfo        */
+                 SHGFI_EXETYPE); /* UINT uFlags            */
+
+  p = LOBYTE (LOWORD (d));
+  e = HIBYTE (LOWORD (d));
+  Trace(("p=%c\ne=%c\nv=%d\n", p, e, HIWORD(d)));
+  return ( (((p=='P') || (p=='N')) && (e=='E')) && (HIWORD(d) != 0) );
+}
+
 /* Copy cygwin environment variables to the Windows environment if they're not
  * already there. */
 static void setup_win_environ(void)
@@ -342,7 +412,7 @@ BOOL configure_startupinfo(STARTUPINFO* 
 
     return TRUE;
 }
-int start_child(char* cmdline, int wait_for_child)
+int start_child(char *exec, char* cmdline, int wait_for_child)
 {
    STARTUPINFO start;
    PROCESS_INFORMATION child;
@@ -392,9 +462,10 @@ int start_child(char* cmdline, int wait_
     */
    bHaveInvisConsole = os_version >= 0x0601 ? TRUE : setup_invisible_console();
    /* Fix issue with 100% CPU usage when launching certain apps from
-    * a cmd.exe box
+    * a cmd.exe box.  However, actual bat files -- that is, cmd.exe
+    * itself -- don't react well to these pipe handles for stdio.
     */
-   bForceUsingPipes = (os_version >= 0x0501);
+   bForceUsingPipes = (os_version >= 0x0501) && (!endsWith(exec,".bat"));
 #endif
 
    if (!configure_startupinfo(&start, bHaveInvisConsole,
@@ -518,29 +589,33 @@ void xemacs_special(char* exec)
       }
    }
 }
-int build_cmdline(char* new_cmdline, char* exec, int argc, char* argv[])
+int build_cmdline(char* new_cmdline, char* exec, int *argc, char* argv[])
 {
    int retval = FALSE;
-   int first_arg = 1;
    int i;
    int char_cnt = 0;
    /*
     * look for "-wait" as first true argument; we'll apply that ourselves
     */
-   if ((argc >= 2) && (stricmp(argv[1],"-wait") == 0))
+   if ((*argc >= 2) && (stricmp(argv[1],"-wait") == 0))
    {
       retval = TRUE;
-      first_arg++;
+      /* remove -wait from argv array */
+      free (argv[1]);
+      for (i = 1; i < *argc-1; i++)
+        argv[i] = argv[i+1];
+      argv[*argc-1] = NULL;
+      *argc -= 1;
    }
 
    char_cnt = strlen(exec);
-   for (i = first_arg; i < argc; i++)
+   for (i = 1; i < *argc; i++)
       char_cnt += strlen(argv[i]);
    if (char_cnt > MAX_ARGS*MAX_PATH) /* then we ran out of room */
       error("command line too long -\n%s",new_cmdline);
 
    strcpy(new_cmdline,exec);
-   for (i = first_arg; i < argc; i++)
+   for (i = 1; i < *argc; i++)
    {
       strcat(new_cmdline," ");
       strcat(new_cmdline,argv[i]);
@@ -737,6 +812,7 @@ void process_execname(char *exec, const 
    strcpy (exec, exec_tmp2);
 #endif
 }
+
 int endsWith(const char* s1, const char* s2)
 {
     int len1;
@@ -748,7 +824,9 @@ int endsWith(const char* s1, const char*
         if (stricmp(&(s1[len1-len2]),s2) == 0)
             retval = TRUE;
     return retval;
-}void strip_exe(char* s)
+}
+
+void strip_exe(char* s)
 {
    if ((strlen(s) > 4) && /* long enough to have .exe extension */
        /* second part not evaluated (short circuit) if exec_arg too short */
Index: src/run.h
===================================================================
RCS file: /cvs/cygwin-apps/run/src/run.h,v
retrieving revision 1.2
diff -u -p -r1.2 run.h
--- src/run.h	16 Aug 2009 03:18:48 -0000	1.2
+++ src/run.h	17 Aug 2009 15:35:54 -0000
@@ -74,7 +74,7 @@
 #endif
 
 #define NUM_EXTENSIONS 2
-const char* exts[NUM_EXTENSIONS] = { "", ".exe" };
+const char* exts[NUM_EXTENSIONS] = { ".exe", "" };
 
 char* pfopen(char *retval, const char *name, const char *dirs);
 void error(char* fmt, ...);
@@ -84,9 +84,9 @@ int get_exec_name_and_path(char* execnam
 char* my_strtok(char* s, const char* delim, char** lasts);
 int parse_cmdline_to_arg_array(char* argv[MAX_ARGS], char* cmdline);
 void strip_exe(char* s);
-int start_child(char* cmdline, int wait_for_child);
+int start_child(char *exec, char* cmdline, int wait_for_child);
 void xemacs_special(char* exec);
-int build_cmdline(char* new_cmdline, char* exec, int argc, char* argv[]);
+int build_cmdline(char* new_cmdline, char* exec, int *argc, char* argv[]);
 void process_execname(char *exec, const char* execname, const char* execpath);
 int fileExists(char* fullname, const char* path, const char* name);
 int endsWith(const char* s1, const char* s2);
--
Problem reports:       http://cygwin.com/problems.html
FAQ:                   http://cygwin.com/faq/
Documentation:         http://cygwin.com/docs.html
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple

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