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{
291413 char cmd [MAXPGPATH ];
292414 char line [100 ];
293- FILE * pgver ;
294-
415+
295416 if (find_my_exec (argv0 , retpath ) < 0 )
296417 return -1 ;
297418
298419 /* Trim off program name and keep just directory */
299420 * last_dir_separator (retpath ) = '\0' ;
300-
301421 snprintf (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
307427 snprintf (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 )))
320430 return -1 ;
321-
431+
322432 if (strcmp (line , versionstr ) != 0 )
323433 return -2 ;
324434
0 commit comments