77 *
88 *
99 * IDENTIFICATION
10- * $PostgreSQL: pgsql/src/port/exec.c,v 1.16 2004/06/10 22:26:24 momjian Exp $
10+ * $PostgreSQL: pgsql/src/port/exec.c,v 1.17 2004/07/26 01:48:00 momjian Exp $
1111 *
1212 *-------------------------------------------------------------------------
1313 */
@@ -279,6 +279,128 @@ find_my_exec(const char *argv0, char *retpath)
279279#endif
280280}
281281
282+ /*
283+ * The runtime librarys popen() on win32 does not work when being
284+ * called from a service when running on windows <= 2000, because
285+ * there is no stdin/stdout/stderr.
286+ *
287+ * Executing a command in a pipe and reading the first line from it
288+ * is all we need.
289+ */
290+
291+ static char * pipe_read_line (char * cmd ,char * line ,int maxsize )
292+ {
293+ #ifndef WIN32
294+ FILE * pgver ;
295+
296+ /* flush output buffers in case popen does not... */
297+ fflush (stdout );
298+ fflush (stderr );
299+
300+ if ((pgver = popen (cmd ,"r" ))== NULL )
301+ return NULL ;
302+
303+ if (fgets (line ,maxsize ,pgver )== NULL )
304+ {
305+ perror ("fgets failure" );
306+ return NULL ;
307+ }
308+
309+ if (pclose_check (pgver ))
310+ return NULL ;
311+
312+ return line ;
313+ #else
314+ /* Win32 */
315+ SECURITY_ATTRIBUTES sattr ;
316+ HANDLE childstdoutrd ,childstdoutwr ,childstdoutrddup ;
317+ PROCESS_INFORMATION pi ;
318+ STARTUPINFO si ;
319+ char * retval = NULL ;
320+
321+ sattr .nLength = sizeof (SECURITY_ATTRIBUTES );
322+ sattr .bInheritHandle = TRUE;
323+ sattr .lpSecurityDescriptor = NULL ;
324+
325+ if (!CreatePipe (& childstdoutrd ,& childstdoutwr ,& sattr ,0 ))
326+ return NULL ;
327+
328+ if (!DuplicateHandle (GetCurrentProcess (),
329+ childstdoutrd ,
330+ GetCurrentProcess (),
331+ & childstdoutrddup ,
332+ 0 ,
333+ FALSE,
334+ DUPLICATE_SAME_ACCESS ))
335+ {
336+ CloseHandle (childstdoutrd );
337+ CloseHandle (childstdoutwr );
338+ return NULL ;
339+ }
340+
341+ CloseHandle (childstdoutrd );
342+
343+ ZeroMemory (& pi ,sizeof (pi ));
344+ ZeroMemory (& si ,sizeof (si ));
345+ si .cb = sizeof (si );
346+ si .dwFlags = STARTF_USESTDHANDLES ;
347+ si .hStdError = childstdoutwr ;
348+ si .hStdOutput = childstdoutwr ;
349+ si .hStdInput = INVALID_HANDLE_VALUE ;
350+
351+ if (CreateProcess (NULL ,
352+ cmd ,
353+ NULL ,
354+ NULL ,
355+ TRUE,
356+ 0 ,
357+ NULL ,
358+ NULL ,
359+ & si ,
360+ & pi ))
361+ {
362+ DWORD bytesread = 0 ;
363+ /* Successfully started the process */
364+
365+ ZeroMemory (line ,maxsize );
366+
367+ /* Let's see if we can read */
368+ if (WaitForSingleObject (childstdoutrddup ,10000 )!= WAIT_OBJECT_0 )
369+ {
370+ /* Got timeout */
371+ CloseHandle (pi .hProcess );
372+ CloseHandle (pi .hThread );
373+ CloseHandle (childstdoutwr );
374+ CloseHandle (childstdoutrddup );
375+ return NULL ;
376+ }
377+
378+
379+ /* We try just once */
380+ if (ReadFile (childstdoutrddup ,line ,maxsize ,& bytesread ,NULL )&&
381+ bytesread > 0 )
382+ {
383+ /* So we read some data */
384+ retval = line ;
385+
386+ /* We emulate fgets() behaviour. So if there is no newline
387+ * at the end, we add one... */
388+ if (line [strlen (line )- 1 ]!= '\n' )
389+ strcat (line ,"\n" );
390+ }
391+
392+ CloseHandle (pi .hProcess );
393+ CloseHandle (pi .hThread );
394+ }
395+
396+ CloseHandle (childstdoutwr );
397+ CloseHandle (childstdoutrddup );
398+
399+ return retval ;
400+ #endif
401+ }
402+
403+
282404
283405/*
284406 * Find our binary directory, then make sure the "target" executable
@@ -290,14 +412,12 @@ find_other_exec(const char *argv0, const char *target,
290412{
291413char cmd [MAXPGPATH ];
292414char line [100 ];
293- FILE * pgver ;
294-
415+
295416if (find_my_exec (argv0 ,retpath )< 0 )
296417return -1 ;
297418
298419/* Trim off program name and keep just directory */
299420* last_dir_separator (retpath )= '\0' ;
300-
301421snprintf (retpath + strlen (retpath ),MAXPGPATH - strlen (retpath ),
302422"/%s%s" ,target ,EXE );
303423
@@ -306,19 +426,9 @@ find_other_exec(const char *argv0, const char *target,
306426
307427snprintf (cmd ,sizeof (cmd ),"\"%s\" -V 2>%s" ,retpath ,DEVNULL );
308428
309- /* flush output buffers in case popen does not... */
310- fflush (stdout );
311- fflush (stderr );
312-
313- if ((pgver = popen (cmd ,"r" ))== NULL )
314- return -1 ;
315-
316- if (fgets (line ,sizeof (line ),pgver )== NULL )
317- perror ("fgets failure" );
318-
319- if (pclose_check (pgver ))
429+ if (!pipe_read_line (cmd ,line ,sizeof (line )))
320430return -1 ;
321-
431+
322432if (strcmp (line ,versionstr )!= 0 )
323433return -2 ;
324434