Remove the unneeded win32_spawn() and win32_get_exit_status()

These are not part of the plugin interface, and are not used in Geany
any more after the spawn changes.
This commit is contained in:
Dimitar Zhekov 2015-03-30 20:33:55 +03:00
parent 7bebf64f3d
commit 47a7b507a7
2 changed files with 0 additions and 498 deletions

View File

@ -57,31 +57,6 @@
#include <glib/gstdio.h> #include <glib/gstdio.h>
#include <gdk/gdkwin32.h> #include <gdk/gdkwin32.h>
#define BUFSIZE 4096
#define CMDSIZE 32768
struct _geany_win32_spawn
{
HANDLE hChildStdinRd;
HANDLE hChildStdinWr;
HANDLE hChildStdoutRd;
HANDLE hChildStdoutWr;
HANDLE hChildStderrRd;
HANDLE hChildStderrWr;
HANDLE hInputFile;
HANDLE hStdout;
HANDLE hStderr;
HANDLE processId;
DWORD dwExitCode;
};
typedef struct _geany_win32_spawn geany_win32_spawn;
static gboolean GetContentFromHandle(HANDLE hFile, gchar **content, GError **error);
static HANDLE GetTempFileHandle(GError **error);
static gboolean CreateChildProcess(geany_win32_spawn *gw_spawn, TCHAR *szCmdline,
const TCHAR *dir, GError **error);
static VOID ReadFromPipe(HANDLE hRead, HANDLE hWrite, HANDLE hFile, GError **error);
/* The timer handle used to refresh windows below modal native dialogs. If /* The timer handle used to refresh windows below modal native dialogs. If
* ever more than one dialog can be shown at a time, this needs to be changed * ever more than one dialog can be shown at a time, this needs to be changed
@ -837,17 +812,6 @@ void win32_open_browser(const gchar *uri)
} }
/* Returns TRUE if the command, which child_pid refers to, returned with a successful exit code,
* otherwise FALSE. */
gboolean win32_get_exit_status(GPid child_pid)
{
DWORD exit_code;
GetExitCodeProcess(child_pid, &exit_code);
return (exit_code == 0);
}
static FILE *open_std_handle(DWORD handle, const char *mode) static FILE *open_std_handle(DWORD handle, const char *mode)
{ {
HANDLE lStdHandle; HANDLE lStdHandle;
@ -929,302 +893,10 @@ void win32_init_debug_code(void)
/* create a console window to get log messages on Windows, /* create a console window to get log messages on Windows,
* especially useful when generating tags files */ * especially useful when generating tags files */
debug_setup_console(); debug_setup_console();
/* Enable GLib process spawn debug mode when Geany was started with the debug flag */
g_setenv("G_SPAWN_WIN32_DEBUG", "1", FALSE);
} }
} }
static gchar *create_temp_file(void)
{
gchar *name;
gint fd;
fd = g_file_open_tmp("tmp_XXXXXX", &name, NULL);
if (fd == -1)
name = NULL;
else
close(fd);
return name;
}
/* Sometimes this blocks for 30s before aborting when there are several
* pages of (error) output and sometimes hangs - see the FIXME.
* Also gw_spawn.dwExitCode seems to be not set properly. */
/* Process spawning implementation for Windows, by Pierre Joye.
* Don't call this function directly, use utils_spawn_[a]sync() instead. */
static
gboolean _broken_win32_spawn(const gchar *dir, gchar **argv, gchar **env, GSpawnFlags flags,
gchar **std_out, gchar **std_err, gint *exit_status, GError **error)
{
TCHAR buffer[CMDSIZE]=TEXT("");
TCHAR cmdline[CMDSIZE] = TEXT("");
TCHAR* lpPart[CMDSIZE]={NULL};
DWORD retval = 0;
gint argc = 0, i;
gint cmdpos = 0;
SECURITY_ATTRIBUTES saAttr;
BOOL fSuccess;
geany_win32_spawn gw_spawn;
/* Temp file */
HANDLE hStdoutTempFile = NULL;
HANDLE hStderrTempFile = NULL;
gchar *stdout_content = NULL;
gchar *stderr_content = NULL;
while (argv[argc])
{
++argc;
}
g_return_val_if_fail (std_out == NULL ||
!(flags & G_SPAWN_STDOUT_TO_DEV_NULL), FALSE);
g_return_val_if_fail (std_err == NULL ||
!(flags & G_SPAWN_STDERR_TO_DEV_NULL), FALSE);
if (flags & G_SPAWN_SEARCH_PATH)
{
retval = SearchPath(NULL, argv[0], ".exe", sizeof(buffer), buffer, lpPart);
if (retval > 0)
g_snprintf(cmdline, sizeof(cmdline), "\"%s\"", buffer);
else
g_strlcpy(cmdline, argv[0], sizeof(cmdline));
cmdpos = 1;
}
for (i = cmdpos; i < argc; i++)
{
g_snprintf(cmdline, sizeof(cmdline), "%s %s", cmdline, argv[i]);
/*MessageBox(NULL, cmdline, cmdline, MB_OK);*/
}
if (std_err != NULL)
{
hStderrTempFile = GetTempFileHandle(error);
if (hStderrTempFile == INVALID_HANDLE_VALUE)
{
gchar *msg = g_win32_error_message(GetLastError());
geany_debug("win32_spawn: Second CreateFile failed (%d)", (gint) GetLastError());
g_set_error(error, G_SPAWN_ERROR, G_FILE_ERROR, "%s", msg);
g_free(msg);
return FALSE;
}
}
if (std_out != NULL)
{
hStdoutTempFile = GetTempFileHandle(error);
if (hStdoutTempFile == INVALID_HANDLE_VALUE)
{
gchar *msg = g_win32_error_message(GetLastError());
geany_debug("win32_spawn: Second CreateFile failed (%d)", (gint) GetLastError());
g_set_error(error, G_SPAWN_ERROR, G_FILE_ERROR, "%s", msg);
g_free(msg);
return FALSE;
}
}
/* Set the bInheritHandle flag so pipe handles are inherited. */
saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
saAttr.bInheritHandle = TRUE;
saAttr.lpSecurityDescriptor = NULL;
/* Get the handle to the current STDOUT and STDERR. */
gw_spawn.hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
gw_spawn.hStderr = GetStdHandle(STD_ERROR_HANDLE);
gw_spawn.dwExitCode = 0;
/* Create a pipe for the child process's STDOUT. */
if (! CreatePipe(&(gw_spawn.hChildStdoutRd), &(gw_spawn.hChildStdoutWr), &saAttr, 0))
{
gchar *msg = g_win32_error_message(GetLastError());
geany_debug("win32_spawn: Stdout pipe creation failed (%d)", (gint) GetLastError());
g_set_error(error, G_SPAWN_ERROR, G_FILE_ERROR_PIPE, "%s", msg);
g_free(msg);
return FALSE;
}
/* Ensure that the read handle to the child process's pipe for STDOUT is not inherited.*/
SetHandleInformation(gw_spawn.hChildStdoutRd, HANDLE_FLAG_INHERIT, 0);
/* Create a pipe for the child process's STDERR. */
if (! CreatePipe(&(gw_spawn.hChildStderrRd), &(gw_spawn.hChildStderrWr), &saAttr, 0))
{
gchar *msg = g_win32_error_message(GetLastError());
geany_debug("win32_spawn: Stderr pipe creation failed");
g_set_error(error, G_SPAWN_ERROR, G_FILE_ERROR_PIPE, "%s", msg);
g_free(msg);
return FALSE;
}
/* Ensure that the read handle to the child process's pipe for STDOUT is not inherited.*/
SetHandleInformation(gw_spawn.hChildStderrRd, HANDLE_FLAG_INHERIT, 0);
/* Create a pipe for the child process's STDIN. */
if (! CreatePipe(&(gw_spawn.hChildStdinRd), &(gw_spawn.hChildStdinWr), &saAttr, 0))
{
gchar *msg = g_win32_error_message(GetLastError());
geany_debug("win32_spawn: Stdin pipe creation failed");
g_set_error(error, G_SPAWN_ERROR, G_FILE_ERROR_PIPE, "%s", msg);
g_free(msg);
return FALSE;
}
/* Ensure that the write handle to the child process's pipe for STDIN is not inherited. */
SetHandleInformation(gw_spawn.hChildStdinWr, HANDLE_FLAG_INHERIT, 0);
/* Now create the child process. */
fSuccess = CreateChildProcess(&gw_spawn, cmdline, dir, error);
if (exit_status)
{
*exit_status = gw_spawn.dwExitCode;
}
if (! fSuccess)
{
geany_debug("win32_spawn: Create process failed");
return FALSE;
}
/* Read from pipe that is the standard output for child process. */
if (std_out != NULL)
{
ReadFromPipe(gw_spawn.hChildStdoutRd, gw_spawn.hChildStdoutWr, hStdoutTempFile, error);
if (! GetContentFromHandle(hStdoutTempFile, &stdout_content, error))
{
return FALSE;
}
*std_out = stdout_content;
}
if (std_err != NULL)
{
ReadFromPipe(gw_spawn.hChildStderrRd, gw_spawn.hChildStderrWr, hStderrTempFile, error);
if (! GetContentFromHandle(hStderrTempFile, &stderr_content, error))
{
return FALSE;
}
*std_err = stderr_content;
}
return TRUE;
}
/* Note: g_spawn is broken for receiving both stdio and stderr e.g. when
* running make and there are compile errors. See glib/giowin32.c header
* comment about Windows bugs, e.g. #338943 */
/* Simple replacement for _broken_win32_spawn().
* flags is ignored, G_SPAWN_SEARCH_PATH is implied.
* Don't call this function directly, use utils_spawn_[a]sync() instead.
* Adapted from tm_workspace_create_global_tags(). */
gboolean win32_spawn(const gchar *dir, gchar **argv, gchar **env, GSpawnFlags flags,
gchar **std_out, gchar **std_err, gint *exit_status, GError **error)
{
gint ret;
gboolean fail;
gchar *tmp_file = create_temp_file();
gchar *tmp_errfile = create_temp_file();
gchar *command;
gchar *locale_command;
if (env != NULL)
{
return _broken_win32_spawn(dir, argv, env, flags, std_out, std_err,
exit_status, error);
}
if (!tmp_file || !tmp_errfile)
{
g_warning("%s: Could not create temporary files!", G_STRFUNC);
return FALSE;
}
command = g_strjoinv(" ", argv);
SETPTR(command, g_strdup_printf("cmd.exe /S /C \"%s >%s 2>%s\"",
command, tmp_file, tmp_errfile));
locale_command = g_locale_from_utf8(command, -1, NULL, NULL, NULL);
if (! locale_command)
locale_command = g_strdup(command);
geany_debug("WIN32: actually running command:\n%s", command);
g_chdir(dir);
errno = 0;
ret = system(locale_command);
/* the command can return -1 as an exit code, so check errno also */
fail = ret == -1 && errno;
if (!fail)
{
if (std_out != NULL)
g_file_get_contents(tmp_file, std_out, NULL, NULL);
if (std_err != NULL)
g_file_get_contents(tmp_errfile, std_err, NULL, NULL);
}
else if (error)
g_set_error_literal(error, G_SPAWN_ERROR, errno, g_strerror(errno));
g_free(command);
g_free(locale_command);
g_unlink(tmp_file);
g_free(tmp_file);
g_unlink(tmp_errfile);
g_free(tmp_errfile);
if (exit_status)
*exit_status = ret;
return !fail;
}
static gboolean GetContentFromHandle(HANDLE hFile, gchar **content, GError **error)
{
DWORD filesize;
gchar * buffer;
DWORD dwRead;
filesize = GetFileSize(hFile, NULL);
if (filesize < 1)
{
*content = NULL;
return TRUE;
}
buffer = g_malloc(filesize + 1);
if (! buffer)
{
gchar *msg = g_win32_error_message(GetLastError());
geany_debug("GetContentFromHandle: Alloc failed");
g_set_error(error, G_SPAWN_ERROR, G_SPAWN_ERROR, "%s", msg);
g_free(msg);
return FALSE;
}
SetFilePointer(hFile, 0, NULL, FILE_BEGIN);
if (! ReadFile(hFile, buffer, filesize, &dwRead, NULL) || dwRead == 0)
{
gchar *msg = g_win32_error_message(GetLastError());
geany_debug("GetContentFromHandle: Cannot read tempfile");
g_set_error(error, G_SPAWN_ERROR, G_FILE_ERROR_FAILED, "%s", msg);
g_free(msg);
return FALSE;
}
if (! CloseHandle(hFile))
{
gchar *msg = g_win32_error_message(GetLastError());
geany_debug("GetContentFromHandle: CloseHandle failed (%d)", (gint) GetLastError());
g_set_error(error, G_SPAWN_ERROR, G_FILE_ERROR_FAILED, "%s", msg);
g_free(msg);
g_free(buffer);
*content = NULL;
return FALSE;
}
buffer[filesize] = '\0';
*content = buffer;
return TRUE;
}
gchar *win32_expand_environment_variables(const gchar *str) gchar *win32_expand_environment_variables(const gchar *str)
{ {
gchar expCmdline[32768]; /* 32768 is the limit for ExpandEnvironmentStrings() */ gchar expCmdline[32768]; /* 32768 is the limit for ExpandEnvironmentStrings() */
@ -1236,171 +908,6 @@ gchar *win32_expand_environment_variables(const gchar *str)
} }
static gboolean CreateChildProcess(geany_win32_spawn *gw_spawn, TCHAR *szCmdline,
const TCHAR *dir, GError **error)
{
PROCESS_INFORMATION piProcInfo;
STARTUPINFOW siStartInfo;
BOOL bFuncRetn = FALSE;
gchar *expandedCmdline;
wchar_t w_commandline[CMDSIZE];
wchar_t w_dir[MAX_PATH];
/* Set up members of the PROCESS_INFORMATION structure. */
ZeroMemory(&piProcInfo, sizeof(PROCESS_INFORMATION));
/* Set up members of the STARTUPINFO structure.*/
ZeroMemory(&siStartInfo, sizeof(STARTUPINFO));
siStartInfo.cb = sizeof(STARTUPINFO);
siStartInfo.hStdError = gw_spawn->hChildStderrWr;
siStartInfo.hStdOutput = gw_spawn->hChildStdoutWr;
siStartInfo.hStdInput = gw_spawn->hChildStdinRd;
siStartInfo.dwFlags |= STARTF_USESTDHANDLES;
/* Expand environment variables like %blah%. */
expandedCmdline = win32_expand_environment_variables(szCmdline);
MultiByteToWideChar(CP_UTF8, 0, expandedCmdline, -1, w_commandline, G_N_ELEMENTS(w_commandline));
MultiByteToWideChar(CP_UTF8, 0, dir, -1, w_dir, G_N_ELEMENTS(w_dir));
/* Create the child process. */
bFuncRetn = CreateProcessW(NULL,
w_commandline, /* command line */
NULL, /* process security attributes */
NULL, /* primary thread security attributes */
TRUE, /* handles are inherited */
CREATE_NO_WINDOW, /* creation flags */
NULL, /* use parent's environment */
w_dir, /* use parent's current directory */
&siStartInfo, /* STARTUPINFO pointer */
&piProcInfo); /* receives PROCESS_INFORMATION */
g_free(expandedCmdline);
if (bFuncRetn == 0)
{
gchar *msg = g_win32_error_message(GetLastError());
geany_debug("CreateChildProcess: CreateProcess failed (%s)", msg);
g_set_error(error, G_SPAWN_ERROR, G_SPAWN_ERROR_FAILED, "%s", msg);
g_free(msg);
return FALSE;
}
else
{
gint i;
gsize ms = 30*1000;
/* FIXME: this seems to timeout when there are many lines
* to read - maybe because the child's pipe is full */
for (i = 0; i < 2 &&
WaitForSingleObject(piProcInfo.hProcess, ms) == WAIT_TIMEOUT; i++)
{
ui_set_statusbar(FALSE, _("Process timed out after %.02f s!"), ms / 1000.0F);
geany_debug("CreateChildProcess: timed out");
TerminateProcess(piProcInfo.hProcess, WAIT_TIMEOUT); /* NOTE: This will not kill grandkids. */
}
if (!GetExitCodeProcess(piProcInfo.hProcess, &gw_spawn->dwExitCode))
{
gchar *msg = g_win32_error_message(GetLastError());
geany_debug("GetExitCodeProcess failed: %s", msg);
g_set_error(error, G_SPAWN_ERROR, G_FILE_ERROR_FAILED, "%s", msg);
g_free(msg);
}
CloseHandle(piProcInfo.hProcess);
CloseHandle(piProcInfo.hThread);
return bFuncRetn;
}
return FALSE;
}
static VOID ReadFromPipe(HANDLE hRead, HANDLE hWrite, HANDLE hFile, GError **error)
{
DWORD dwRead, dwWritten;
CHAR chBuf[BUFSIZE];
/* Close the write end of the pipe before reading from the
read end of the pipe. */
if (! CloseHandle(hWrite))
{
gchar *msg = g_win32_error_message(GetLastError());
geany_debug("ReadFromPipe: Closing handle failed");
g_set_error(error, G_SPAWN_ERROR, G_FILE_ERROR_PIPE, "%s", msg);
g_free(msg);
return;
}
/* Read output from the child process, and write to parent's STDOUT. */
for (;;)
{
if (! ReadFile(hRead, chBuf, BUFSIZE, &dwRead, NULL) || dwRead == 0)
break;
if (! WriteFile(hFile, chBuf, dwRead, &dwWritten, NULL))
break;
}
}
static HANDLE GetTempFileHandle(GError **error)
{
/* Temp file */
DWORD dwBufSize = BUFSIZE;
UINT uRetVal;
TCHAR szTempName[BUFSIZE];
TCHAR lpPathBuffer[BUFSIZE];
DWORD dwRetVal;
HANDLE hTempFile;
/* Get the temp path. */
dwRetVal = GetTempPath(dwBufSize, /* length of the buffer*/
lpPathBuffer); /* buffer for path */
if (dwRetVal > dwBufSize || (dwRetVal == 0))
{
gchar *msg = g_win32_error_message(GetLastError());
geany_debug("GetTempFileHandle: GetTempPath failed (%d)", (gint) GetLastError());
g_set_error(error, G_SPAWN_ERROR, G_FILE_ERROR, "%s", msg);
g_free(msg);
return NULL;
}
/* Create a temporary file for STDOUT. */
uRetVal = GetTempFileName(lpPathBuffer, /* directory for tmp files */
TEXT("GEANY_VCDIFF_"), /* temp file name prefix */
0, /* create unique name */
szTempName); /* buffer for name */
if (uRetVal == 0)
{
gchar *msg = g_win32_error_message(GetLastError());
geany_debug("GetTempFileName failed (%d)", (gint) GetLastError());
g_set_error(error, G_SPAWN_ERROR, G_FILE_ERROR, "%s", msg);
g_free(msg);
return NULL;
}
hTempFile = CreateFile((LPTSTR) szTempName, /* file name */
GENERIC_READ | GENERIC_WRITE, /* open r-w */
0, /* do not share */
NULL, /* default security */
CREATE_ALWAYS, /* overwrite existing */
FILE_ATTRIBUTE_NORMAL,/* normal file */
NULL); /* no template */
if (hTempFile == INVALID_HANDLE_VALUE)
{
gchar *msg = g_win32_error_message(GetLastError());
geany_debug("GetTempFileHandle: Second CreateFile failed (%d)", (gint) GetLastError());
g_set_error(error, G_SPAWN_ERROR, G_FILE_ERROR, "%s", msg);
g_free(msg);
return NULL;
}
return hTempFile;
}
/* From GDK (they got it from MS Knowledge Base article Q130698) */ /* From GDK (they got it from MS Knowledge Base article Q130698) */
static gboolean resolve_link(HWND hWnd, wchar_t *link, gchar **lpszPath) static gboolean resolve_link(HWND hWnd, wchar_t *link, gchar **lpszPath)
{ {

View File

@ -60,11 +60,6 @@ void win32_init_debug_code(void);
void win32_set_working_directory(const gchar *dir); void win32_set_working_directory(const gchar *dir);
gboolean win32_get_exit_status(GPid child_pid);
gboolean win32_spawn(const gchar *dir, gchar **argv, gchar **env, GSpawnFlags flags,
gchar **std_out, gchar **std_err, gint *exit_status, GError **error);
gchar *win32_get_shortcut_target(const gchar *file_name); gchar *win32_get_shortcut_target(const gchar *file_name);
gchar *win32_get_installation_dir(void); gchar *win32_get_installation_dir(void);