@@ -195,10 +195,10 @@ stop_postmaster_atexit(void)
195195bool
196196start_postmaster (ClusterInfo * cluster , bool report_and_exit_on_error )
197197{
198- char cmd [MAXPGPATH * 4 + 1000 ];
199198 PGconn * conn ;
200199 bool pg_ctl_return = false;
201- char socket_string [MAXPGPATH + 200 ];
200+ PQExpBufferData cmd ;
201+ PQExpBufferData opts ;
202202
203203 static bool exit_hook_registered = false;
204204
@@ -208,22 +208,28 @@ start_postmaster(ClusterInfo *cluster, bool report_and_exit_on_error)
208208 exit_hook_registered = true;
209209 }
210210
211- socket_string [ 0 ] = '\0' ;
211+ initPQExpBuffer ( & cmd ) ;
212212
213- #ifdef HAVE_UNIX_SOCKETS
214- /* prevent TCP/IP connections, restrict socket access */
215- strcat (socket_string ,
216- " -c listen_addresses='' -c unix_socket_permissions=0700" );
213+ /* Path to pg_ctl */
214+ appendPQExpBuffer (& cmd , "\"%s/pg_ctl\" -w " , cluster -> bindir );
217215
218- /* Have a sockdir? Tell the postmaster. */
219- if (cluster -> sockdir )
220- snprintf (socket_string + strlen (socket_string ),
221- sizeof (socket_string ) - strlen (socket_string ),
222- " -c %s='%s'" ,
223- (GET_MAJOR_VERSION (cluster -> major_version ) < 903 ) ?
224- "unix_socket_directory" : "unix_socket_directories" ,
225- cluster -> sockdir );
226- #endif
216+ /* log file */
217+ appendPQExpBufferStr (& cmd , "-l " );
218+ appendShellString (& cmd , SERVER_LOG_FILE );
219+ appendPQExpBufferChar (& cmd , ' ' );
220+
221+ /* data folder */
222+ appendPQExpBufferStr (& cmd , "-D " );
223+ appendShellString (& cmd , cluster -> pgconfig );
224+ appendPQExpBufferChar (& cmd , ' ' );
225+
226+ /*
227+ * Build set of options for the instance to start. These are handled with
228+ * a separate string as they are one argument in the command produced to
229+ * which shell quoting needs to be applied.
230+ */
231+ initPQExpBuffer (& opts );
232+ appendPQExpBuffer (& opts , "-p %d " , cluster -> port );
227233
228234 /*
229235 * Since PG 9.1, we have used -b to disable autovacuum. For earlier
@@ -234,21 +240,52 @@ start_postmaster(ClusterInfo *cluster, bool report_and_exit_on_error)
234240 * is no need to set that.) We assume all datfrozenxid and relfrozenxid
235241 * values are less than a gap of 2000000000 from the current xid counter,
236242 * so autovacuum will not touch them.
237- *
243+ */
244+ if (cluster -> controldata .cat_ver >= BINARY_UPGRADE_SERVER_FLAG_CAT_VER )
245+ appendPQExpBufferStr (& opts , "-b " );
246+ else
247+ appendPQExpBufferStr (& opts ,
248+ "-c autovacuum=off "
249+ "-c autovacuum_freeze_max_age=2000000000 " );
250+
251+ /*
238252 * Turn off durability requirements to improve object creation speed, and
239253 * we only modify the new cluster, so only use it there. If there is a
240254 * crash, the new cluster has to be recreated anyway. fsync=off is a big
241255 * win on ext4.
242256 */
243- snprintf (cmd , sizeof (cmd ),
244- "\"%s/pg_ctl\" -w -l \"%s\" -D \"%s\" -o \"-p %d%s%s %s%s\" start" ,
245- cluster -> bindir , SERVER_LOG_FILE , cluster -> pgconfig , cluster -> port ,
246- (cluster -> controldata .cat_ver >=
247- BINARY_UPGRADE_SERVER_FLAG_CAT_VER ) ? " -b" :
248- " -c autovacuum=off -c autovacuum_freeze_max_age=2000000000" ,
249- (cluster == & new_cluster ) ?
250- " -c synchronous_commit=off -c fsync=off -c full_page_writes=off" : "" ,
251- cluster -> pgopts ? cluster -> pgopts : "" , socket_string );
257+ if (cluster == & new_cluster )
258+ appendPQExpBufferStr (& opts ,
259+ "-c synchronous_commit=off "
260+ "-c fsync=off "
261+ "-c full_page_writes=off " );
262+
263+ if (cluster -> pgopts )
264+ appendPQExpBufferStr (& opts , cluster -> pgopts );
265+
266+ #ifdef HAVE_UNIX_SOCKETS
267+ appendPQExpBuffer (& opts ,
268+ "-c listen_addresses='' -c unix_socket_permissions=0700 " );
269+
270+ /* Have a sockdir? Tell the postmaster. */
271+ if (cluster -> sockdir )
272+ {
273+ appendPQExpBuffer (& opts ,
274+ " -c %s=" ,
275+ (GET_MAJOR_VERSION (cluster -> major_version ) < 903 ) ?
276+ "unix_socket_directory" : "unix_socket_directories" );
277+ appendPQExpBufferStr (& opts , cluster -> sockdir );
278+ appendPQExpBufferChar (& opts , ' ' );
279+ }
280+ #endif
281+
282+ /* Apply shell quoting to the option string */
283+ appendPQExpBufferStr (& cmd , "-o " );
284+ appendShellString (& cmd , opts .data );
285+ termPQExpBuffer (& opts );
286+
287+ /* Start mode for pg_ctl */
288+ appendPQExpBufferStr (& cmd , " start" );
252289
253290 /*
254291 * Don't throw an error right away, let connecting throw the error because
@@ -260,7 +297,7 @@ start_postmaster(ClusterInfo *cluster, bool report_and_exit_on_error)
260297 SERVER_START_LOG_FILE ) != 0 ) ?
261298 SERVER_LOG_FILE : NULL ,
262299 report_and_exit_on_error , false,
263- "%s" , cmd );
300+ "%s" , cmd . data );
264301
265302 /* Did it fail and we are just testing if the server could be started? */
266303 if (!pg_ctl_return && !report_and_exit_on_error )
@@ -298,13 +335,14 @@ start_postmaster(ClusterInfo *cluster, bool report_and_exit_on_error)
298335 if (cluster == & old_cluster )
299336 pg_fatal ("could not connect to source postmaster started with the command:\n"
300337 "%s\n" ,
301- cmd );
338+ cmd . data );
302339 else
303340 pg_fatal ("could not connect to target postmaster started with the command:\n"
304341 "%s\n" ,
305- cmd );
342+ cmd . data );
306343 }
307344 PQfinish (conn );
345+ termPQExpBuffer (& cmd );
308346
309347 /*
310348 * If pg_ctl failed, and the connection didn't fail, and
0 commit comments