@@ -141,7 +141,6 @@ static bool postmaster_is_alive(pid_t pid);
141141
142142static char postopts_file [MAXPGPATH ];
143143static char pid_file [MAXPGPATH ];
144- static char conf_file [MAXPGPATH ];
145144static char backup_file [MAXPGPATH ];
146145static char recovery_file [MAXPGPATH ];
147146
@@ -404,113 +403,108 @@ start_postmaster(void)
404403static PGPing
405404test_postmaster_connection (bool do_checkpoint )
406405{
406+ int portnum = 0 ;
407+ char socket_dir [MAXPGPATH ];
408+ char connstr [MAXPGPATH + 256 ];
407409PGPing ret = PQPING_OK ;/* assume success for wait == zero */
410+ char * * optlines ;
408411int i ;
409- char portstr [32 ];
410- char * p ;
411- char * q ;
412- char connstr [128 ];/* Should be way more than enough! */
413412
414- portstr [0 ]= '\0' ;
415-
416- /*
417- * Look in post_opts for a -p switch.
418- *
419- * This parsing code is not amazingly bright; it could for instance get
420- * fooled if ' -p' occurs within a quoted argument value. Given that few
421- * people pass complicated settings in post_opts, it's probably good
422- * enough.
423- */
424- for (p = post_opts ;* p ;)
413+ socket_dir [0 ]= '\0' ;
414+ connstr [0 ]= '\0' ;
415+
416+ for (i = 0 ;i < wait_seconds ;i ++ )
425417{
426- /* advance past whitespace */
427- while (isspace ((unsignedchar )* p ))
428- p ++ ;
429-
430- if (strncmp (p ,"-p" ,2 )== 0 )
418+ /* Do we need a connection string? */
419+ if (connstr [0 ]== '\0' )
431420{
432- p += 2 ;
433- /* advance past any whitespace/quoting */
434- while (isspace ((unsignedchar )* p )|| * p == '\'' || * p == '"' )
435- p ++ ;
436- /* find end of value (not including any ending quote!) */
437- q = p ;
438- while (* q &&
439- !(isspace ((unsignedchar )* q )|| * q == '\'' || * q == '"' ))
440- q ++ ;
441- /* and save the argument value */
442- strlcpy (portstr ,p ,Min ((q - p )+ 1 ,sizeof (portstr )));
443- /* keep looking, maybe there is another -p */
444- p = q ;
445- }
446- /* Advance to next whitespace */
447- while (* p && !isspace ((unsignedchar )* p ))
448- p ++ ;
449- }
421+ /*
422+ * The number of lines in postmaster.pid tells us several things:
423+ *
424+ *# of lines
425+ *0lock file created but status not written
426+ *2pre-9.1 server, shared memory not created
427+ *3pre-9.1 server, shared memory created
428+ *49.1+ server, shared memory not created
429+ *59.1+ server, shared memory created
430+ *
431+ *For pre-9.1 Unix servers, we grab the port number from the
432+ *shmem key (first value on line 3). Pre-9.1 Win32 has no
433+ *written shmem key, so we fail. 9.1+ writes both the port
434+ *number and socket address in the file for us to use.
435+ *(PG_VERSION could also have told us the major version.)
436+ */
437+
438+ /* Try to read a completed postmaster.pid file */
439+ if ((optlines = readfile (pid_file ))!= NULL &&
440+ optlines [0 ]!= NULL &&
441+ optlines [1 ]!= NULL &&
442+ optlines [2 ]!= NULL )
443+ {
444+ /* A 3-line file? */
445+ if (optlines [3 ]== NULL )
446+ {
447+ /*
448+ *Pre-9.1: on Unix, we get the port number by
449+ *deriving it from the shmem key (the first number on
450+ *on the line); see
451+ *miscinit.c::RecordSharedMemoryInLockFile().
452+ */
453+ portnum = atoi (optlines [2 ]) /1000 ;
454+ /* Win32 does not give us a shmem key, so we fail. */
455+ if (portnum == 0 )
456+ {
457+ write_stderr (_ ("%s: -w option is not supported on this platform\nwhen connecting to a pre-9.1 server\n" ),
458+ progname );
459+ return PQPING_NO_ATTEMPT ;
460+ }
461+ }
462+ else /* 9.1+ server */
463+ {
464+ portnum = atoi (optlines [2 ]);
465+
466+ /* Get socket directory, if specified. */
467+ if (optlines [3 ][0 ]!= '\n' )
468+ {
469+ /*
470+ *While unix_socket_directory can accept relative
471+ *directories, libpq's host must have a leading slash
472+ *to indicate a socket directory.
473+ */
474+ if (optlines [3 ][0 ]!= '/' )
475+ {
476+ write_stderr (_ ("%s: -w option cannot use a relative socket directory specification\n" ),
477+ progname );
478+ return PQPING_NO_ATTEMPT ;
479+ }
480+ strlcpy (socket_dir ,optlines [3 ],MAXPGPATH );
481+ /* remove newline */
482+ if (strchr (socket_dir ,'\n' )!= NULL )
483+ * strchr (socket_dir ,'\n' )= '\0' ;
484+ }
485+ }
450486
451- /*
452- * Search config file for a 'port' option.
453- *
454- * This parsing code isn't amazingly bright either, but it should be okay
455- * for valid port settings.
456- */
457- if (!portstr [0 ])
458- {
459- char * * optlines ;
487+ /*
488+ * We need to set connect_timeout otherwise on Windows the
489+ * Service Control Manager (SCM) will probably timeout first.
490+ */
491+ snprintf (connstr ,sizeof (connstr ),
492+ "dbname=postgres port=%d connect_timeout=5" ,portnum );
460493
461- optlines = readfile (conf_file );
462- if (optlines != NULL )
463- {
464- for (;* optlines != NULL ;optlines ++ )
465- {
466- p = * optlines ;
467-
468- while (isspace ((unsignedchar )* p ))
469- p ++ ;
470- if (strncmp (p ,"port" ,4 )!= 0 )
471- continue ;
472- p += 4 ;
473- while (isspace ((unsignedchar )* p ))
474- p ++ ;
475- if (* p != '=' )
476- continue ;
477- p ++ ;
478- /* advance past any whitespace/quoting */
479- while (isspace ((unsignedchar )* p )|| * p == '\'' || * p == '"' )
480- p ++ ;
481- /* find end of value (not including any ending quote/comment!) */
482- q = p ;
483- while (* q &&
484- !(isspace ((unsignedchar )* q )||
485- * q == '\'' || * q == '"' || * q == '#' ))
486- q ++ ;
487- /* and save the argument value */
488- strlcpy (portstr ,p ,Min ((q - p )+ 1 ,sizeof (portstr )));
489- /* keep looking, maybe there is another */
494+ if (socket_dir [0 ]!= '\0' )
495+ snprintf (connstr + strlen (connstr ),sizeof (connstr )- strlen (connstr ),
496+ " host='%s'" ,socket_dir );
490497}
491498}
492- }
493499
494- /* Check environment */
495- if (!portstr [0 ]&& getenv ("PGPORT" )!= NULL )
496- strlcpy (portstr ,getenv ("PGPORT" ),sizeof (portstr ));
497-
498- /* Else use compiled-in default */
499- if (!portstr [0 ])
500- snprintf (portstr ,sizeof (portstr ),"%d" ,DEF_PGPORT );
501-
502- /*
503- * We need to set a connect timeout otherwise on Windows the SCM will
504- * probably timeout first
505- */
506- snprintf (connstr ,sizeof (connstr ),
507- "dbname=postgres port=%s connect_timeout=5" ,portstr );
500+ /* If we have a connection string, ping the server */
501+ if (connstr [0 ]!= '\0' )
502+ {
503+ ret = PQping (connstr );
504+ if (ret == PQPING_OK || ret == PQPING_NO_ATTEMPT )
505+ break ;
506+ }
508507
509- for (i = 0 ;i < wait_seconds ;i ++ )
510- {
511- ret = PQping (connstr );
512- if (ret == PQPING_OK || ret == PQPING_NO_ATTEMPT )
513- break ;
514508/* No response, or startup still in process; wait */
515509#if defined(WIN32 )
516510if (do_checkpoint )
@@ -2009,7 +2003,6 @@ main(int argc, char **argv)
20092003{
20102004snprintf (postopts_file ,MAXPGPATH , "%s /postmaster .opts ",pg_data );
20112005snprintf (pid_file ,MAXPGPATH , "%s /postmaster .pid ",pg_data );
2012- snprintf (conf_file ,MAXPGPATH , "%s /postgresql .conf ",pg_data );
20132006snprintf (backup_file ,MAXPGPATH , "%s /backup_label ",pg_data );
20142007snprintf (recovery_file ,MAXPGPATH , "%s /recovery .conf ",pg_data );
20152008}