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 #include #include +#include #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);