[PATCH 1/1] Apply application logging approach for vpnc-script output

Ľubomír Carik lubomir.carik at gmail.com
Sun Apr 15 14:08:53 PDT 2018


- inherit handlers for child process
- update close app handles
- update flags

Signed-off-by: Ľubomír Carik <Lubomir.Carik at gmail.com>
---
 openconnect.h |   2 ++
 script.c      | 104 +++++++++++++++++++++++++++++++++++++++++++++++++++-------
 2 files changed, 94 insertions(+), 12 deletions(-)

diff --git a/openconnect.h b/openconnect.h
index e97dacbc..75dfdd18 100644
--- a/openconnect.h
+++ b/openconnect.h
@@ -29,6 +29,8 @@ extern "C" {
 #endif
 
 #ifdef _WIN32
+#include <winsock2.h>
+
 #define uid_t unsigned
 #endif
 
diff --git a/script.c b/script.c
index 5b751ad5..695ebd38 100644
--- a/script.c
+++ b/script.c
@@ -24,6 +24,8 @@
 #include <unistd.h>
 #ifndef _WIN32
 #include <sys/wait.h>
+#else
+#include <stdbool.h>
 #endif
 #include <errno.h>
 #include <ctype.h>
@@ -32,6 +34,15 @@
 
 #include "openconnect-internal.h"
 
+#ifdef _WIN32
+#define BUFSIZE 4096
+
+HANDLE g_hChildStd_OUT_Rd = NULL;
+HANDLE g_hChildStd_OUT_Wr = NULL;
+HANDLE g_hChildStd_ERR_Rd = NULL;
+HANDLE g_hChildStd_ERR_Wr = NULL;
+#endif
+
 int script_setenv(struct openconnect_info *vpninfo,
 		  const char *opt, const char *val, int append)
 {
@@ -459,17 +470,52 @@ int script_config_tun(struct openconnect_info *vpninfo, const char *reason)
 	int ret;
 	char *cmd;
 	PROCESS_INFORMATION pi;
+	SECURITY_ATTRIBUTES sa;
 	STARTUPINFOW si;
 	DWORD cpflags;
 
+	DWORD dwRead = 0;
+	CHAR chBuf[BUFSIZE];
+	bool bSuccess = FALSE;
+	char* token = NULL;
+
 	if (!vpninfo->vpnc_script || vpninfo->script_tun)
 		return 0;
 
-	memset(&si, 0, sizeof(si));
-	si.cb = sizeof(si);
+	// Set the bInheritHandle flag so pipe handles are inherited.
+	sa.nLength = sizeof(SECURITY_ATTRIBUTES);
+	sa.bInheritHandle = TRUE;
+	sa.lpSecurityDescriptor = NULL;
+	// Create a pipe for the child process's STDERR.
+	if (!CreatePipe(&g_hChildStd_ERR_Rd, &g_hChildStd_ERR_Wr, &sa, 0)) {
+		return -EPIPE;
+	}
+	// Ensure the read handle to the pipe for STDERR is not inherited.
+	if (!SetHandleInformation(g_hChildStd_ERR_Rd, HANDLE_FLAG_INHERIT, 0)) {
+		return -EPIPE;
+	}
+	// Create a pipe for the child process's STDOUT.
+	if (!CreatePipe(&g_hChildStd_OUT_Rd, &g_hChildStd_OUT_Wr, &sa, 0)) {
+		return -EPIPE;
+	}
+	// Ensure the read handle to the pipe for STDOUT is not inherited
+	if (!SetHandleInformation(g_hChildStd_OUT_Rd, HANDLE_FLAG_INHERIT, 0)) {
+		return -EPIPE;
+	}
+
+	// Set up members of the PROCESS_INFORMATION structure.
+	ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));
+
+	// Set up members of the STARTUPINFO structure.
+	// This structure specifies the STDERR and STDOUT handles for redirection.
+	ZeroMemory(&si, sizeof(STARTUPINFO));
+	si.cb = sizeof(STARTUPINFO);
 	/* probably superfluous */
-	si.dwFlags = STARTF_USESHOWWINDOW;
+	si.dwFlags |= STARTF_USESHOWWINDOW;
+	si.dwFlags |= STARTF_USESTDHANDLES;
 	si.wShowWindow = SW_HIDE;
+	si.hStdError = g_hChildStd_ERR_Wr;
+	si.hStdOutput = g_hChildStd_OUT_Wr;
 
 	script_setenv(vpninfo, "reason", reason, 0);
 
@@ -495,19 +541,53 @@ int script_config_tun(struct openconnect_info *vpninfo, const char *reason)
 	if (!GetConsoleWindow())
 		cpflags |= CREATE_NO_WINDOW;
 
-	if (CreateProcessW(NULL, script_w, NULL, NULL, FALSE, cpflags,
-			   script_env, NULL, &si, &pi)) {
-		ret = WaitForSingleObject(pi.hProcess,10000);
-		CloseHandle(pi.hThread);
-		CloseHandle(pi.hProcess);
-		if (ret == WAIT_TIMEOUT)
-			ret = -ETIMEDOUT;
-		else
-			ret = 0;
+	if (CreateProcessW(NULL,
+		script_w, // command line
+		NULL, // process security attributes
+		NULL, // primary thread security attributes
+		TRUE, // handles are inherited
+		cpflags, // creation flags
+		script_env, // use parent's environment
+		NULL, // use parent's current directory
+		&si, // STARTUPINFO pointer
+		&pi) // receives PROCESS_INFORMATION
+        ) {
+		CloseHandle(g_hChildStd_ERR_Wr);
+		CloseHandle(g_hChildStd_OUT_Wr);
+		ret = 0;
 	} else {
 		ret = -EIO;
 	}
 
+	// Read from pipe that is the standard output for child process.
+	for (;;) {
+		bSuccess = ReadFile(g_hChildStd_OUT_Rd, chBuf, BUFSIZE, &dwRead, NULL);
+		if (!bSuccess || dwRead == 0) break;
+
+		chBuf[dwRead] = 0;
+		token = strtok(chBuf, "\r\n");
+		while (token) {
+			vpn_progress(vpninfo, PRG_INFO,
+						 _("vpnc: %s\n"),
+						 token);
+			token = strtok(NULL, "\r\n");
+		}
+	}
+	dwRead = 0;
+	for (;;) {
+		bSuccess = ReadFile(g_hChildStd_ERR_Rd, chBuf, BUFSIZE, &dwRead, NULL);
+		if (!bSuccess || dwRead == 0) break;
+
+		chBuf[dwRead] = 0;
+		token = strtok(chBuf, "\r\n");
+		while (token) {
+			vpn_progress(vpninfo, PRG_ERR,
+						 _("vpnc: %s\n"),
+						 token);
+			token = strtok(NULL, "\r\n");
+		}
+	}
+
 	free(script_env);
 
 	if (ret < 0) {
-- 
2.16.2




More information about the openconnect-devel mailing list