diff options
author | Gerald Combs <gerald@wireshark.org> | 2018-03-01 15:31:45 -0800 |
---|---|---|
committer | Anders Broman <a.broman58@gmail.com> | 2018-03-02 05:22:20 +0000 |
commit | 1a0987904fa571dc5abce03726e4ca3e17793574 (patch) | |
tree | 59b7bfe30517005b046bddb9fcae2315f48570fa /extcap_spawn.c | |
parent | bf4c2fd82b30d8b088fcb1235263dce9173d4cd7 (diff) |
Generalize our process spawning code.
Move the contents of extcap_spawn to ws_pipe. Rename various extcap_*
prefixes to ws_pipe_*. Open stdin when we spawn processes.
Change-Id: I9286295443ee955bb6328b0ed6f945ee0bb2a798
Reviewed-on: https://code.wireshark.org/review/26216
Reviewed-by: Gerald Combs <gerald@wireshark.org>
Petri-Dish: Gerald Combs <gerald@wireshark.org>
Tested-by: Petri Dish Buildbot
Reviewed-by: Anders Broman <a.broman58@gmail.com>
Diffstat (limited to 'extcap_spawn.c')
-rw-r--r-- | extcap_spawn.c | 381 |
1 files changed, 0 insertions, 381 deletions
diff --git a/extcap_spawn.c b/extcap_spawn.c deleted file mode 100644 index 816e0e3a5f..0000000000 --- a/extcap_spawn.c +++ /dev/null @@ -1,381 +0,0 @@ -/* extcap_spawn.c - * - * Routines to spawn extcap external capture programs - * Copyright 2016, Roland Knall <rknall@gmail.com> - * - * Wireshark - Network traffic analyzer - * By Gerald Combs <gerald@wireshark.org> - * Copyright 1998 Gerald Combs - * - * SPDX-License-Identifier: GPL-2.0-or-later - */ - -#include <config.h> - -#include <stdio.h> -#include <glib.h> -#include <string.h> - -#include <wsutil/file_util.h> -#include <wsutil/filesystem.h> -#include <wsutil/ws_pipe.h> -#ifdef _WIN32 -#include <wsutil/win32-utils.h> -#endif - -#include <log.h> - -#include "extcap.h" -#include "extcap_spawn.h" - -gboolean extcap_spawn_sync(gchar *dirname, gchar *command, gint argc, gchar **args, gchar **command_output) -{ - gboolean status = FALSE; - gboolean result = FALSE; - gchar **argv = NULL; - gint cnt = 0; - gchar *local_output = NULL; -#ifdef _WIN32 - -#define BUFFER_SIZE 16384 - - GString *winargs = g_string_sized_new(200); - gchar *quoted_arg; - gunichar2 *wcommandline; - - STARTUPINFO info; - PROCESS_INFORMATION processInfo; - - SECURITY_ATTRIBUTES sa; - HANDLE child_stdout_rd = NULL; - HANDLE child_stdout_wr = NULL; - HANDLE child_stderr_rd = NULL; - HANDLE child_stderr_wr = NULL; - - const gchar *oldpath = g_getenv("PATH"); - gchar *newpath = NULL; -#else - gint exit_status = 0; -#endif - - argv = (gchar **) g_malloc0(sizeof(gchar *) * (argc + 2)); - -#ifdef _WIN32 - newpath = g_strdup_printf("%s;%s", g_strescape(get_progfile_dir(), NULL), oldpath); - g_setenv("PATH", newpath, TRUE); - - argv[0] = g_strescape(command, NULL); -#else - argv[0] = g_strdup(command); -#endif - - for (cnt = 0; cnt < argc; cnt++) - argv[cnt + 1] = args[cnt]; - argv[argc + 1] = NULL; - -#ifdef _WIN32 - - sa.nLength = sizeof(SECURITY_ATTRIBUTES); - sa.bInheritHandle = TRUE; - sa.lpSecurityDescriptor = NULL; - - if (!CreatePipe(&child_stdout_rd, &child_stdout_wr, &sa, 0)) - { - g_free(argv[0]); - g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "Could not create stdout handle"); - return FALSE; - } - - if (!CreatePipe(&child_stderr_rd, &child_stderr_wr, &sa, 0)) - { - CloseHandle(child_stdout_rd); - CloseHandle(child_stdout_wr); - g_free(argv[0]); - g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "Could not create stderr handle"); - return FALSE; - } - - /* convert args array into a single string */ - /* XXX - could change sync_pipe_add_arg() instead */ - /* there is a drawback here: the length is internally limited to 1024 bytes */ - for (cnt = 0; argv[cnt] != 0; cnt++) { - if (cnt != 0) g_string_append_c(winargs, ' '); /* don't prepend a space before the path!!! */ - quoted_arg = protect_arg(argv[cnt]); - g_string_append(winargs, quoted_arg); - g_free(quoted_arg); - } - - wcommandline = g_utf8_to_utf16(winargs->str, (glong)winargs->len, NULL, NULL, NULL); - - memset(&processInfo, 0, sizeof(PROCESS_INFORMATION)); - memset(&info, 0, sizeof(STARTUPINFO)); - - info.cb = sizeof(STARTUPINFO); - info.hStdError = child_stderr_wr; - info.hStdOutput = child_stdout_wr; - info.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW; - info.wShowWindow = SW_HIDE; - - if (CreateProcess(NULL, wcommandline, NULL, NULL, TRUE, CREATE_NEW_CONSOLE, NULL, NULL, &info, &processInfo)) - { - gchar* buffer; - - WaitForSingleObject(processInfo.hProcess, INFINITE); - buffer = (gchar*)g_malloc(BUFFER_SIZE); - status = ws_read_string_from_pipe(child_stdout_rd, buffer, BUFFER_SIZE); - if (status) - { - local_output = g_strdup_printf("%s", buffer); - } - g_free(buffer); - - CloseHandle(child_stdout_rd); - CloseHandle(child_stdout_wr); - CloseHandle(child_stderr_rd); - CloseHandle(child_stderr_wr); - - CloseHandle(processInfo.hProcess); - CloseHandle(processInfo.hThread); - } - else - status = FALSE; - - g_setenv("PATH", oldpath, TRUE); -#else - - status = g_spawn_sync(dirname, argv, NULL, - (GSpawnFlags) 0, NULL, NULL, &local_output, NULL, &exit_status, NULL); - - if (status && exit_status != 0) - status = FALSE; -#endif - - if (status) - { - if (command_output != NULL && local_output != NULL) - *command_output = g_strdup(local_output); - - result = TRUE; - } - - g_free(local_output); - g_free(argv[0]); - g_free(argv); - - return result; -} - -GPid extcap_spawn_async(extcap_userdata *userdata, GPtrArray *args) -{ - GPid pid = INVALID_EXTCAP_PID; - -#ifdef _WIN32 - gint cnt = 0; - gchar **tmp = NULL; - - GString *winargs = g_string_sized_new(200); - gchar *quoted_arg; - gunichar2 *wcommandline; - - STARTUPINFO info; - PROCESS_INFORMATION processInfo; - - SECURITY_ATTRIBUTES sa; - HANDLE child_stdout_rd = NULL; - HANDLE child_stdout_wr = NULL; - HANDLE child_stderr_rd = NULL; - HANDLE child_stderr_wr = NULL; - - const gchar *oldpath = g_getenv("PATH"); - gchar *newpath = NULL; - - newpath = g_strdup_printf("%s;%s", g_strescape(get_progfile_dir(), NULL), oldpath); - g_setenv("PATH", newpath, TRUE); - - sa.nLength = sizeof(SECURITY_ATTRIBUTES); - sa.bInheritHandle = TRUE; - sa.lpSecurityDescriptor = NULL; - - if (!CreatePipe(&child_stdout_rd, &child_stdout_wr, &sa, 0)) - { - g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "Could not create stdout handle"); - return FALSE; - } - - if (!CreatePipe(&child_stderr_rd, &child_stderr_wr, &sa, 0)) - { - CloseHandle(child_stdout_rd); - CloseHandle(child_stdout_wr); - g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "Could not create stderr handle"); - return FALSE; - } - - /* convert args array into a single string */ - /* XXX - could change sync_pipe_add_arg() instead */ - /* there is a drawback here: the length is internally limited to 1024 bytes */ - for (tmp = (gchar **)args->pdata, cnt = 0; *tmp && **tmp; ++cnt, ++tmp) { - if (cnt != 0) g_string_append_c(winargs, ' '); /* don't prepend a space before the path!!! */ - quoted_arg = protect_arg(*tmp); - g_string_append(winargs, quoted_arg); - g_free(quoted_arg); - } - - wcommandline = g_utf8_to_utf16(winargs->str, (glong)winargs->len, NULL, NULL, NULL); - - memset(&processInfo, 0, sizeof(PROCESS_INFORMATION)); - memset(&info, 0, sizeof(STARTUPINFO)); - - info.cb = sizeof(STARTUPINFO); - info.hStdError = child_stderr_wr; - info.hStdOutput = child_stdout_wr; - info.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW; - info.wShowWindow = SW_HIDE; - - if (CreateProcess(NULL, wcommandline, NULL, NULL, TRUE, CREATE_NEW_CONSOLE, NULL, NULL, &info, &processInfo)) - { - userdata->extcap_stderr_rd = _open_osfhandle((intptr_t)(child_stderr_rd), _O_BINARY); - userdata->extcap_stdout_rd = _open_osfhandle((intptr_t)(child_stdout_rd), _O_BINARY); - userdata->threadId = processInfo.hThread; - pid = processInfo.hProcess; - } - - g_setenv("PATH", oldpath, TRUE); -#else - g_spawn_async_with_pipes(NULL, (gchar **)args->pdata, NULL, - (GSpawnFlags) G_SPAWN_DO_NOT_REAP_CHILD, NULL, NULL, - &pid, NULL, &userdata->extcap_stdout_rd, &userdata->extcap_stderr_rd, NULL); -#endif - - userdata->pid = pid; - - return pid; -} - -#ifdef _WIN32 - -typedef struct -{ - HANDLE pipeHandle; - OVERLAPPED ol; - BOOL pendingIO; -} PIPEINTS; - -gboolean -extcap_wait_for_pipe(HANDLE * pipe_handles, int num_pipe_handles, HANDLE pid) -{ - PIPEINTS pipeinsts[3]; - DWORD dw, cbRet; - HANDLE handles[4]; - int error_code; - int num_waiting_to_connect = 0; - int num_handles = num_pipe_handles + 1; // PID handle is also added to list of handles. - - if (num_pipe_handles == 0 || num_pipe_handles > 3) - { - g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "Invalid number of pipes given as argument."); - return FALSE; - } - - for (int i = 0; i < num_pipe_handles; ++i) - { - pipeinsts[i].pipeHandle = pipe_handles[i]; - pipeinsts[i].ol.Pointer = 0; - pipeinsts[i].ol.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL); - pipeinsts[i].pendingIO = FALSE; - handles[i] = pipeinsts[i].ol.hEvent; - BOOL connected = ConnectNamedPipe(pipeinsts[i].pipeHandle, &pipeinsts[i].ol); - if (connected) - { - error_code = GetLastError(); - g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "ConnectNamedPipe failed with %d \n.", error_code); - return FALSE; - } - - switch (GetLastError()) - { - case ERROR_IO_PENDING: - num_waiting_to_connect++; - pipeinsts[i].pendingIO = TRUE; - break; - - case ERROR_PIPE_CONNECTED: - if (SetEvent(pipeinsts[i].ol.hEvent)) - { - break; - } // Fallthrough if this fails. - - default: - error_code = GetLastError(); - g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "ConnectNamedPipe failed with %d \n.", error_code); - return FALSE; - } - } - - // Store pid of extcap process so it can be monitored in case it fails before the pipes has connceted. - handles[num_pipe_handles] = pid; - - while(num_waiting_to_connect > 0) - { - dw = WaitForMultipleObjects(num_handles, handles, FALSE, 30000); - int idx = dw - WAIT_OBJECT_0; - if (dw == WAIT_TIMEOUT) - { - g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "extcap didn't connect to pipe within 30 seconds."); - return FALSE; - } - // If index points to our handles array - else if (idx >= 0 && idx < num_handles) - { - if (idx < num_pipe_handles) // Index of pipe handle - { - if (pipeinsts[idx].pendingIO) - { - BOOL success = GetOverlappedResult( - pipeinsts[idx].pipeHandle, // handle to pipe - &pipeinsts[idx].ol, // OVERLAPPED structure - &cbRet, // bytes transferred - FALSE); // do not wait - - if (!success) - { - g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "Error %d \n.", GetLastError()); - return FALSE; - } - else - { - pipeinsts[idx].pendingIO = FALSE; - CloseHandle(pipeinsts[idx].ol.hEvent); - num_waiting_to_connect--; - } - } - } - else // Index of PID - { - // Fail since index of 'pid' indicates that the pid of the extcap process has terminated. - g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "extcap terminated without connecting to pipe."); - return FALSE; - } - } - else - { - g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "WaitForMultipleObjects returned 0x%08X. Error %d", dw, GetLastError()); - return FALSE; - } - } - - return TRUE; -} -#endif - -/* - * Editor modelines - http://www.wireshark.org/tools/modelines.html - * - * Local variables: - * c-basic-offset: 4 - * tab-width: 8 - * indent-tabs-mode: nil - * End: - * - * vi: set shiftwidth=4 tabstop=8 expandtab: - * :indentSize=4:tabSize=8:noTabs=true: - */ |