From 5b2f4afffe6972ecc61c506576f6e40787dc19ec Mon Sep 17 00:00:00 2001
From: Bruce Momjian <bruce@momjian.us>
Date: Mon, 26 Jul 2004 01:48:00 +0000
Subject: [PATCH] Here is a patch that fixes the pipes used in
 find_other_exec() when running as a service on windows <= 2000. Required to
 make the pg_ctl service wrapper to work at all.

Magnus Hagander
---
 doc/src/sgml/release.sgml |   4 +-
 src/port/exec.c           | 142 +++++++++++++++++++++++++++++++++-----
 2 files changed, 128 insertions(+), 18 deletions(-)

diff --git a/doc/src/sgml/release.sgml b/doc/src/sgml/release.sgml
index 10360fc1e5a..b2c0be4edab 100644
--- a/doc/src/sgml/release.sgml
+++ b/doc/src/sgml/release.sgml
@@ -1,5 +1,5 @@
 <!--
-$PostgreSQL: pgsql/doc/src/sgml/release.sgml,v 1.270 2004/07/26 00:26:42 momjian Exp $
+$PostgreSQL: pgsql/doc/src/sgml/release.sgml,v 1.271 2004/07/26 01:47:59 momjian Exp $
 -->
 
 <appendix id="release">
@@ -1271,7 +1271,7 @@ $PostgreSQL: pgsql/doc/src/sgml/release.sgml,v 1.270 2004/07/26 00:26:42 momjian
 
     <listitem>
      <para>
-      New start/end of dump markers in pg_dump (Bruce)
+      New start/stop of dump markers in pg_dump (Bruce)
      </para>
     </listitem>
 
diff --git a/src/port/exec.c b/src/port/exec.c
index c8ba1227a15..d98da090c70 100644
--- a/src/port/exec.c
+++ b/src/port/exec.c
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/port/exec.c,v 1.16 2004/06/10 22:26:24 momjian Exp $
+ *	  $PostgreSQL: pgsql/src/port/exec.c,v 1.17 2004/07/26 01:48:00 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -279,6 +279,128 @@ find_my_exec(const char *argv0, char *retpath)
 #endif
 }
 
+/*
+ * The runtime librarys popen() on win32 does not work when being
+ * called from a service when running on windows <= 2000, because
+ * there is no stdin/stdout/stderr.
+ *
+ * Executing a command in a pipe and reading the first line from it
+ * is all we need.
+ */
+	
+static char *pipe_read_line(char *cmd, char *line, int maxsize)
+{
+#ifndef WIN32
+	FILE *pgver;
+
+	/* flush output buffers in case popen does not... */
+	fflush(stdout);
+	fflush(stderr);
+
+	if ((pgver = popen(cmd, "r")) == NULL)
+		return NULL;
+	
+	if (fgets(line, maxsize, pgver) == NULL)
+	{
+		perror("fgets failure");
+		return NULL;
+	}
+
+	if (pclose_check(pgver))
+		return NULL;
+	
+	return line;
+#else
+	/* Win32 */
+	SECURITY_ATTRIBUTES sattr;
+	HANDLE childstdoutrd, childstdoutwr, childstdoutrddup;
+	PROCESS_INFORMATION pi;
+	STARTUPINFO si;
+	char *retval = NULL;
+
+	sattr.nLength = sizeof(SECURITY_ATTRIBUTES);
+	sattr.bInheritHandle = TRUE;
+	sattr.lpSecurityDescriptor = NULL;
+
+	if (!CreatePipe(&childstdoutrd, &childstdoutwr, &sattr, 0))
+		return NULL;
+	
+	if (!DuplicateHandle(GetCurrentProcess(),
+						 childstdoutrd,
+						 GetCurrentProcess(),
+						 &childstdoutrddup,
+						 0,
+						 FALSE,
+						 DUPLICATE_SAME_ACCESS))
+	{
+		CloseHandle(childstdoutrd);
+		CloseHandle(childstdoutwr);
+		return NULL;
+	}
+
+	CloseHandle(childstdoutrd);
+	
+	ZeroMemory(&pi,sizeof(pi));
+	ZeroMemory(&si,sizeof(si));
+	si.cb = sizeof(si);
+	si.dwFlags = STARTF_USESTDHANDLES;
+	si.hStdError = childstdoutwr;
+	si.hStdOutput = childstdoutwr;
+	si.hStdInput = INVALID_HANDLE_VALUE;
+	
+	if (CreateProcess(NULL,
+					  cmd,
+					  NULL,
+					  NULL,
+					  TRUE,
+					  0,
+					  NULL,
+					  NULL,
+					  &si,
+					  &pi))
+	{
+		DWORD bytesread = 0;
+		/* Successfully started the process */
+
+		ZeroMemory(line,maxsize);
+		
+		/* Let's see if we can read */
+		if (WaitForSingleObject(childstdoutrddup, 10000) != WAIT_OBJECT_0) 
+		{
+			/* Got timeout */
+			CloseHandle(pi.hProcess);
+			CloseHandle(pi.hThread);
+			CloseHandle(childstdoutwr);
+			CloseHandle(childstdoutrddup);
+			return NULL;
+		}
+		
+		
+		/* We try just once */
+		if (ReadFile(childstdoutrddup, line, maxsize, &bytesread, NULL) &&
+			bytesread > 0)
+		{
+			/* So we read some data */
+			retval = line;
+
+			/* We emulate fgets() behaviour. So if there is no newline
+			 * at the end, we add one... */
+			if (line[strlen(line)-1] != '\n')
+				strcat(line,"\n");
+		}
+
+		CloseHandle(pi.hProcess);
+		CloseHandle(pi.hThread);
+	}
+	
+	CloseHandle(childstdoutwr);
+	CloseHandle(childstdoutrddup);
+
+	return retval;
+#endif
+}
+	
+
 
 /*
  * Find our binary directory, then make sure the "target" executable
@@ -290,14 +412,12 @@ find_other_exec(const char *argv0, const char *target,
 {
 	char		cmd[MAXPGPATH];
 	char		line[100];
-	FILE	   *pgver;
-
+	
 	if (find_my_exec(argv0, retpath) < 0)
 		return -1;
 
 	/* Trim off program name and keep just directory */	
 	*last_dir_separator(retpath) = '\0';
-
 	snprintf(retpath + strlen(retpath), MAXPGPATH - strlen(retpath),
 			 "/%s%s", target, EXE);
 
@@ -306,19 +426,9 @@ find_other_exec(const char *argv0, const char *target,
 	
 	snprintf(cmd, sizeof(cmd), "\"%s\" -V 2>%s", retpath, DEVNULL);
 
-	/* flush output buffers in case popen does not... */
-	fflush(stdout);
-	fflush(stderr);
-
-	if ((pgver = popen(cmd, "r")) == NULL)
-		return -1;
-
-	if (fgets(line, sizeof(line), pgver) == NULL)
-		perror("fgets failure");
-
-	if (pclose_check(pgver))
+	if (!pipe_read_line(cmd, line, sizeof(line)))
 		return -1;
-
+	
 	if (strcmp(line, versionstr) != 0)
 		return -2;
 
-- 
GitLab