aboutsummaryrefslogtreecommitdiffstats
path: root/extcap_spawn.c
diff options
context:
space:
mode:
authorGerald Combs <gerald@wireshark.org>2018-03-01 15:31:45 -0800
committerAnders Broman <a.broman58@gmail.com>2018-03-02 05:22:20 +0000
commit1a0987904fa571dc5abce03726e4ca3e17793574 (patch)
tree59b7bfe30517005b046bddb9fcae2315f48570fa /extcap_spawn.c
parentbf4c2fd82b30d8b088fcb1235263dce9173d4cd7 (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.c381
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:
- */