Index: src/port/exec.c =================================================================== RCS file: /projects/cvsroot/pgsql-server/src/port/exec.c,v retrieving revision 1.16 diff -c -r1.16 exec.c *** src/port/exec.c 10 Jun 2004 22:26:24 -0000 1.16 --- src/port/exec.c 24 Jul 2004 17:08:59 -0000 *************** *** 279,284 **** --- 279,406 ---- #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,303 **** { 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); --- 412,423 ---- { char cmd[MAXPGPATH]; char line[100]; ! 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,324 **** 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)) return -1; ! if (strcmp(line, versionstr) != 0) return -2; --- 426,434 ---- snprintf(cmd, sizeof(cmd), "\"%s\" -V 2>%s", retpath, DEVNULL); ! if (!pipe_read_line(cmd, line, sizeof(line))) return -1; ! if (strcmp(line, versionstr) != 0) return -2;