@@ -196,10 +196,10 @@ stop_postmaster_atexit(void)
196
196
bool
197
197
start_postmaster (ClusterInfo * cluster ,bool report_and_exit_on_error )
198
198
{
199
- char cmd [MAXPGPATH * 4 + 1000 ];
200
199
PGconn * conn ;
201
200
bool pg_ctl_return = false;
202
- char socket_string [MAXPGPATH + 200 ];
201
+ PQExpBufferData cmd ;
202
+ PQExpBufferData opts ;
203
203
204
204
static bool exit_hook_registered = false;
205
205
@@ -209,22 +209,28 @@ start_postmaster(ClusterInfo *cluster, bool report_and_exit_on_error)
209
209
exit_hook_registered = true;
210
210
}
211
211
212
- socket_string [ 0 ] = '\0' ;
212
+ initPQExpBuffer ( & cmd ) ;
213
213
214
- #ifdef HAVE_UNIX_SOCKETS
215
- /* prevent TCP/IP connections, restrict socket access */
216
- strcat (socket_string ,
217
- " -c listen_addresses='' -c unix_socket_permissions=0700" );
214
+ /* Path to pg_ctl */
215
+ appendPQExpBuffer (& cmd ,"\"%s/pg_ctl\" -w " ,cluster -> bindir );
218
216
219
- /* Have a sockdir?Tell the postmaster. */
220
- if (cluster -> sockdir )
221
- snprintf (socket_string + strlen (socket_string ),
222
- sizeof (socket_string )- strlen (socket_string ),
223
- " -c %s='%s'" ,
224
- (GET_MAJOR_VERSION (cluster -> major_version )< 903 ) ?
225
- "unix_socket_directory" :"unix_socket_directories" ,
226
- cluster -> sockdir );
227
- #endif
217
+ /* log file */
218
+ appendPQExpBufferStr (& cmd ,"-l " );
219
+ appendShellString (& cmd ,SERVER_LOG_FILE );
220
+ appendPQExpBufferChar (& cmd ,' ' );
221
+
222
+ /* data folder */
223
+ appendPQExpBufferStr (& cmd ,"-D " );
224
+ appendShellString (& cmd ,cluster -> pgconfig );
225
+ appendPQExpBufferChar (& cmd ,' ' );
226
+
227
+ /*
228
+ * Build set of options for the instance to start. These are
229
+ * handled with a separate string as they are one argument in
230
+ * the command produced to which shell quoting needs to be applied.
231
+ */
232
+ initPQExpBuffer (& opts );
233
+ appendPQExpBuffer (& opts ,"-p %d " ,cluster -> port );
228
234
229
235
/*
230
236
* Since PG 9.1, we have used -b to disable autovacuum. For earlier
@@ -235,21 +241,52 @@ start_postmaster(ClusterInfo *cluster, bool report_and_exit_on_error)
235
241
* is no need to set that.) We assume all datfrozenxid and relfrozenxid
236
242
* values are less than a gap of 2000000000 from the current xid counter,
237
243
* so autovacuum will not touch them.
238
- *
244
+ */
245
+ if (cluster -> controldata .cat_ver >=BINARY_UPGRADE_SERVER_FLAG_CAT_VER )
246
+ appendPQExpBufferStr (& opts ,"-b " );
247
+ else
248
+ appendPQExpBufferStr (& opts ,
249
+ "-c autovacuum=off "
250
+ "-c autovacuum_freeze_max_age=2000000000 " );
251
+
252
+ /*
239
253
* Turn off durability requirements to improve object creation speed, and
240
254
* we only modify the new cluster, so only use it there. If there is a
241
255
* crash, the new cluster has to be recreated anyway. fsync=off is a big
242
256
* win on ext4.
243
257
*/
244
- snprintf (cmd ,sizeof (cmd ),
245
- "\"%s/pg_ctl\" -w -l \"%s\" -D \"%s\" -o \"-p %d%s%s %s%s\" start" ,
246
- cluster -> bindir ,SERVER_LOG_FILE ,cluster -> pgconfig ,cluster -> port ,
247
- (cluster -> controldata .cat_ver >=
248
- BINARY_UPGRADE_SERVER_FLAG_CAT_VER ) ?" -b" :
249
- " -c autovacuum=off -c autovacuum_freeze_max_age=2000000000" ,
250
- (cluster == & new_cluster ) ?
251
- " -c synchronous_commit=off -c fsync=off -c full_page_writes=off" :"" ,
252
- cluster -> pgopts ?cluster -> pgopts :"" ,socket_string );
258
+ if (cluster == & new_cluster )
259
+ appendPQExpBufferStr (& opts ,
260
+ "-c synchronous_commit=off "
261
+ "-c fsync=off "
262
+ "-c full_page_writes=off " );
263
+
264
+ if (cluster -> pgopts )
265
+ appendPQExpBufferStr (& opts ,cluster -> pgopts );
266
+
267
+ #ifdef HAVE_UNIX_SOCKETS
268
+ appendPQExpBuffer (& opts ,
269
+ "-c listen_addresses='' -c unix_socket_permissions=0700 " );
270
+
271
+ /* Have a sockdir?Tell the postmaster. */
272
+ if (cluster -> sockdir )
273
+ {
274
+ appendPQExpBuffer (& opts ,
275
+ " -c %s=" ,
276
+ (GET_MAJOR_VERSION (cluster -> major_version )< 903 ) ?
277
+ "unix_socket_directory" :"unix_socket_directories" );
278
+ appendPQExpBufferStr (& opts ,cluster -> sockdir );
279
+ appendPQExpBufferChar (& opts ,' ' );
280
+ }
281
+ #endif
282
+
283
+ /* Apply shell quoting to the option string */
284
+ appendPQExpBufferStr (& cmd ,"-o " );
285
+ appendShellString (& cmd ,opts .data );
286
+ termPQExpBuffer (& opts );
287
+
288
+ /* Start mode for pg_ctl */
289
+ appendPQExpBufferStr (& cmd ," start" );
253
290
254
291
/*
255
292
* Don't throw an error right away, let connecting throw the error because
@@ -261,7 +298,7 @@ start_postmaster(ClusterInfo *cluster, bool report_and_exit_on_error)
261
298
SERVER_START_LOG_FILE )!= 0 ) ?
262
299
SERVER_LOG_FILE :NULL ,
263
300
report_and_exit_on_error , false,
264
- "%s" ,cmd );
301
+ "%s" ,cmd . data );
265
302
266
303
/* Did it fail and we are just testing if the server could be started? */
267
304
if (!pg_ctl_return && !report_and_exit_on_error )
@@ -299,13 +336,14 @@ start_postmaster(ClusterInfo *cluster, bool report_and_exit_on_error)
299
336
if (cluster == & old_cluster )
300
337
pg_fatal ("could not connect to source postmaster started with the command:\n"
301
338
"%s\n" ,
302
- cmd );
339
+ cmd . data );
303
340
else
304
341
pg_fatal ("could not connect to target postmaster started with the command:\n"
305
342
"%s\n" ,
306
- cmd );
343
+ cmd . data );
307
344
}
308
345
PQfinish (conn );
346
+ termPQExpBuffer (& cmd );
309
347
310
348
/*
311
349
* If pg_ctl failed, and the connection didn't fail, and