#include "getaddrinfo.h"
 #include "getopt_long.h"
 #include "miscadmin.h"
+#include "fe_utils/string_utils.h"
 
 
 /* Define PG_FLUSH_DATA_WORKS if we have an implementation for pg_flush_data */
                output_failed = true, output_errno = errno; \
 } while (0)
 
-#ifndef WIN32
-#define QUOTE_PATH     ""
-#define DIR_SEP "/"
-#else
-#define QUOTE_PATH     "\""
-#define DIR_SEP "\\"
-#endif
-
 static char *
 escape_quotes(const char *src)
 {
        int                     c;
        int                     option_index;
        char       *effective_user;
-       char            bin_dir[MAXPGPATH];
+       PQExpBuffer start_db_cmd;
+       char            pg_ctl_path[MAXPGPATH];
 
        /*
         * Ensure that buffering behavior of stdout and stderr matches what it is
        if (authwarning != NULL)
                fprintf(stderr, "%s", authwarning);
 
-       /* Get directory specification used to start this executable */
-       strlcpy(bin_dir, argv[0], sizeof(bin_dir));
-       get_parent_directory(bin_dir);
+       /*
+        * Build up a shell command to tell the user how to start the server
+        */
+       start_db_cmd = createPQExpBuffer();
+
+       /* Get directory specification used to start initdb ... */
+       strlcpy(pg_ctl_path, argv[0], sizeof(pg_ctl_path));
+       canonicalize_path(pg_ctl_path);
+       get_parent_directory(pg_ctl_path);
+       /* ... and tag on pg_ctl instead */
+       join_path_components(pg_ctl_path, pg_ctl_path, "pg_ctl");
+
+       /* path to pg_ctl, properly quoted */
+       appendShellString(start_db_cmd, pg_ctl_path);
+
+       /* add -D switch, with properly quoted data directory */
+       appendPQExpBufferStr(start_db_cmd, " -D ");
+       appendShellString(start_db_cmd, pgdata_native);
+
+       /* add suggested -l switch and "start" command */
+       appendPQExpBufferStr(start_db_cmd, " -l logfile start");
 
        printf(_("\nSuccess. You can now start the database server using:\n\n"
-                        "    %s%s%spg_ctl%s -D %s%s%s -l logfile start\n\n"),
-          QUOTE_PATH, bin_dir, (strlen(bin_dir) > 0) ? DIR_SEP : "", QUOTE_PATH,
-                  QUOTE_PATH, pgdata_native, QUOTE_PATH);
+                        "        %s\n\n"),
+                  start_db_cmd->data);
+
+       destroyPQExpBuffer(start_db_cmd);
 
        return 0;
 }
 
 
 /*
  * Append the given string to the shell command being built in the buffer,
- * with suitable shell-style quoting to create exactly one argument.
+ * with shell-style quoting as needed to create exactly one argument.
  *
  * Forbid LF or CR characters, which have scant practical use beyond designing
  * security breaches.  The Windows command shell is unusable as a conduit for
 void
 appendShellString(PQExpBuffer buf, const char *str)
 {
+#ifdef WIN32
+       int                     backslash_run_length = 0;
+#endif
        const char *p;
 
+       /*
+        * Don't bother with adding quotes if the string is nonempty and clearly
+        * contains only safe characters.
+        */
+       if (*str != '\0' &&
+               strspn(str, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_./:") == strlen(str))
+       {
+               appendPQExpBufferStr(buf, str);
+               return;
+       }
+
 #ifndef WIN32
        appendPQExpBufferChar(buf, '\'');
        for (p = str; *p; p++)
        }
        appendPQExpBufferChar(buf, '\'');
 #else                                                  /* WIN32 */
-       int                     backslash_run_length = 0;
 
        /*
         * A Windows system() argument experiences two layers of interpretation.