]> granicus.if.org Git - postgresql/blobdiff - src/bin/initdb/initdb.c
>I got a new idea on this. I think we should add an initdb option that
[postgresql] / src / bin / initdb / initdb.c
index 7b9e2d5b3b848a1684d787183035108d979aa007..cd830ecda7a6215baf255e72e363c63b77d54b2e 100644 (file)
@@ -39,7 +39,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  * Portions taken from FreeBSD.
  *
- * $PostgreSQL: pgsql/src/bin/initdb/initdb.c,v 1.30 2004/05/17 13:17:29 momjian Exp $
+ * $PostgreSQL: pgsql/src/bin/initdb/initdb.c,v 1.45 2004/08/01 05:59:13 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -52,6 +52,9 @@
 #include <locale.h>
 #include <signal.h>
 #include <errno.h>
+#ifdef HAVE_LANGINFO_H
+# include <langinfo.h>
+#endif
 
 #include "libpq/pqsignal.h"
 #include "mb/pg_wchar.h"
@@ -69,11 +72,8 @@ int                  optreset;
 
 /*
  * these values are passed in by makefile defines
- *
- * Note that "datadir" is not the directory we're going to initialize,
- * it's merely how Autoconf names PREFIX/share.
  */
-char      *datadir = PGDATADIR;
+char           *share_path = NULL;
 
 /* values to be obtained from arguments */
 char      *pg_data = "";
@@ -87,6 +87,8 @@ char     *lc_time = "";
 char      *lc_messages = "";
 char      *username = "";
 bool           pwprompt = false;
+char       *pwfilename = NULL;
+char       *authmethod = "";
 bool           debug = false;
 bool           noclean = false;
 bool           show_setting = false;
@@ -117,6 +119,16 @@ bool               output_failed = false;
 int                    n_connections = 10;
 int                    n_buffers = 50;
 
+/*
+ * Warning messages for authentication methods
+ */
+char *authtrust_warning =                                                                                      \
+       "# CAUTION: Configuring the system for local \"trust\" authentication allows\n"
+       "# any local user to connect as any PostgreSQL user, including the database\n"
+       "# superuser. If you do not trust all your local users, use another\n"
+       "# authenication method.\n";
+char *authwarning = NULL;
+
 /*
  * Centralized knowledge of switches to pass to backend
  *
@@ -129,7 +141,7 @@ static const char *backend_options = "-F -O -c search_path=pg_catalog -c exit_on
 
 
 /* path to 'initdb' binary directory */
-char      bindir[MAXPGPATH];
+char      bin_path[MAXPGPATH];
 char      backend_exec[MAXPGPATH];
 
 static void *xmalloc(size_t size);
@@ -144,7 +156,7 @@ static char *get_id(void);
 static char *get_encoding_id(char *encoding_name);
 static char *get_short_version(void);
 static int check_data_dir(void);
-static bool mkdatadir(char *subdir);
+static bool mkdatadir(const char *subdir);
 static void set_input(char **dest, char *filename);
 static void check_input(char *path);
 static void set_short_version(char *short_version, char *extrapath);
@@ -170,7 +182,6 @@ static void check_ok(void);
 static bool chklocale(const char *locale);
 static void setlocales(void);
 static void usage(const char *progname);
-static void init_nls(void);
 
 
 /*
@@ -603,6 +614,15 @@ get_id(void)
        return xstrdup(pw->pw_name);
 }
 
+static char *
+encodingid_to_string(int enc)
+{
+       char            result[20];
+
+       sprintf(result, "%d", enc);
+       return xstrdup(result);
+}
+
 /*
  * get the encoding id for a given encoding name
  */
@@ -610,15 +630,13 @@ static char *
 get_encoding_id(char *encoding_name)
 {
        int                     enc;
-       char            result[20];
 
        if (encoding_name && *encoding_name)
        {
                if ((enc = pg_char_to_encoding(encoding_name)) >= 0 &&
                        pg_valid_server_encoding(encoding_name) >= 0)
                {
-                       sprintf(result, "%d", enc);
-                       return xstrdup(result);
+                       return encodingid_to_string(enc);
                }
        }
        fprintf(stderr, _("%s: \"%s\" is not a valid server encoding name\n"),
@@ -626,6 +644,191 @@ get_encoding_id(char *encoding_name)
        exit(1);
 }
 
+#ifdef HAVE_LANGINFO_H
+/*
+ * Checks whether the encoding selected for PostgreSQL and the
+ * encoding used by the system locale match.
+ */
+
+struct encoding_match
+{
+       enum pg_enc     pg_enc_code;
+       char       *system_enc_name;
+};
+
+struct encoding_match encoding_match_list[] = {
+       { PG_EUC_JP, "EUC-JP" },
+       { PG_EUC_JP, "eucJP" },
+       { PG_EUC_JP, "IBM-eucJP" },
+       { PG_EUC_JP, "sdeckanji" },
+
+       { PG_EUC_CN, "EUC-CN" },
+       { PG_EUC_CN, "eucCN" },
+       { PG_EUC_CN, "IBM-eucCN" },
+       { PG_EUC_CN, "GB2312" },
+       { PG_EUC_CN, "dechanzi" },
+
+       { PG_EUC_KR, "EUC-KR" },
+       { PG_EUC_KR, "eucKR" },
+       { PG_EUC_KR, "IBM-eucKR" },
+       { PG_EUC_KR, "deckorean" },
+       { PG_EUC_KR, "5601" },
+
+       { PG_EUC_TW, "EUC-TW" },
+       { PG_EUC_TW, "eucTW" },
+       { PG_EUC_TW, "IBM-eucTW" },
+       { PG_EUC_TW, "cns11643" },
+
+#ifdef NOT_VERIFIED
+       { PG_JOHAB, "???" },
+#endif
+
+       { PG_UTF8, "UTF-8" },
+       { PG_UTF8, "utf8" },
+
+       { PG_LATIN1, "ISO-8859-1" },
+       { PG_LATIN1, "ISO8859-1" },
+       { PG_LATIN1, "iso88591" },
+
+       { PG_LATIN2, "ISO-8859-2" },
+       { PG_LATIN2, "ISO8859-2" },
+       { PG_LATIN2, "iso88592" },
+
+       { PG_LATIN3, "ISO-8859-3" },
+       { PG_LATIN3, "ISO8859-3" },
+       { PG_LATIN3, "iso88593" },
+
+       { PG_LATIN4, "ISO-8859-4" },
+       { PG_LATIN4, "ISO8859-4" },
+       { PG_LATIN4, "iso88594" },
+
+       { PG_LATIN5, "ISO-8859-9" },
+       { PG_LATIN5, "ISO8859-9" },
+       { PG_LATIN5, "iso88599" },
+
+       { PG_LATIN6, "ISO-8859-10" },
+       { PG_LATIN6, "ISO8859-10" },
+       { PG_LATIN6, "iso885910" },
+
+       { PG_LATIN7, "ISO-8859-13" },
+       { PG_LATIN7, "ISO8859-13" },
+       { PG_LATIN7, "iso885913" },
+
+       { PG_LATIN8, "ISO-8859-14" },
+       { PG_LATIN8, "ISO8859-14" },
+       { PG_LATIN8, "iso885914" },
+
+       { PG_LATIN9, "ISO-8859-15" },
+       { PG_LATIN9, "ISO8859-15" },
+       { PG_LATIN9, "iso885915" },
+
+       { PG_LATIN10, "ISO-8859-16" },
+       { PG_LATIN10, "ISO8859-16" },
+       { PG_LATIN10, "iso885916" },
+
+       { PG_WIN1256, "CP1256" },
+       { PG_TCVN, "CP1258" },
+#ifdef NOT_VERIFIED
+       { PG_WIN874, "???" },
+#endif
+       { PG_KOI8R, "KOI8-R" },
+       { PG_WIN1251, "CP1251" },
+       { PG_ALT, "CP866" },
+
+       { PG_ISO_8859_5, "ISO-8859-5" },
+       { PG_ISO_8859_5, "ISO8859-5" },
+       { PG_ISO_8859_5, "iso88595" },
+
+       { PG_ISO_8859_6, "ISO-8859-6" },
+       { PG_ISO_8859_6, "ISO8859-6" },
+       { PG_ISO_8859_6, "iso88596" },
+
+       { PG_ISO_8859_7, "ISO-8859-7" },
+       { PG_ISO_8859_7, "ISO8859-7" },
+       { PG_ISO_8859_7, "iso88597" },
+
+       { PG_ISO_8859_8, "ISO-8859-8" },
+       { PG_ISO_8859_8, "ISO8859-8" },
+       { PG_ISO_8859_8, "iso88598" },
+
+       { PG_SQL_ASCII, NULL } /* end marker */
+};
+
+static char *
+get_encoding_from_locale(const char *ctype)
+{
+       char       *save;
+       char       *sys;
+
+       save = setlocale(LC_CTYPE, NULL);
+       if (!save)
+               return NULL;
+       save = xstrdup(save);
+
+       setlocale(LC_CTYPE, ctype);
+       sys = nl_langinfo(CODESET);
+       sys = xstrdup(sys);
+
+       setlocale(LC_CTYPE, save);
+       free(save);
+
+       return sys;
+}
+
+static void
+check_encodings_match(int pg_enc, const char *ctype)
+{
+       char *sys;
+       int i;
+
+       sys = get_encoding_from_locale(ctype);
+
+       for (i = 0; encoding_match_list[i].system_enc_name; i++)
+       {
+               if (pg_enc == encoding_match_list[i].pg_enc_code
+                       && strcasecmp(sys, encoding_match_list[i].system_enc_name) == 0)
+               {
+                       free(sys);
+                       return;
+               }
+       }
+
+       fprintf(stderr,
+                       _("%s: warning: encoding mismatch\n"), progname);
+       fprintf(stderr,
+                       _("The encoding you selected (%s) and the encoding that the selected\n"
+                         "locale uses (%s) are not known to match.  This may lead to\n"
+                         "misbehavior in various character string processing functions.  To fix\n"
+                         "this situation, rerun %s and either do not specify an encoding\n"
+                         "explicitly, or choose a matching combination.\n"),
+                       pg_encoding_to_char(pg_enc), sys, progname);
+
+       free(sys);
+       return;
+}
+
+static int
+find_matching_encoding(const char *ctype)
+{
+       char *sys;
+       int i;
+
+       sys = get_encoding_from_locale(ctype);
+
+       for (i = 0; encoding_match_list[i].system_enc_name; i++)
+       {
+               if (strcasecmp(sys, encoding_match_list[i].system_enc_name) == 0)
+               {
+                       free(sys);
+                       return encoding_match_list[i].pg_enc_code;
+               }
+       }
+
+       free(sys);
+       return -1;
+}
+#endif /* HAVE_LANGINFO_H */
+
 /*
  * get short version of VERSION
  */
@@ -708,7 +911,7 @@ check_data_dir(void)
  * make the data directory (or one of its subdirectories if subdir is not NULL)
  */
 static bool
-mkdatadir(char *subdir)
+mkdatadir(const char *subdir)
 {
        char       *path;
 
@@ -730,8 +933,8 @@ mkdatadir(char *subdir)
 static void
 set_input(char **dest, char *filename)
 {
-       *dest = xmalloc(strlen(datadir) + strlen(filename) + 2);
-       sprintf(*dest, "%s/%s", datadir, filename);
+       *dest = xmalloc(strlen(share_path) + strlen(filename) + 2);
+       sprintf(*dest, "%s/%s", share_path, filename);
 }
 
 /*
@@ -816,12 +1019,12 @@ test_connections(void)
        for (i = 0; i < len; i++)
        {
                snprintf(cmd, sizeof(cmd),
-                                "\"%s\" -boot -x0 %s "
+                                "%s\"%s\" -boot -x0 %s "
                                 "-c shared_buffers=%d -c max_connections=%d template1 "
-                                "<%s >%s 2>&1",
-                                backend_exec, boot_options,
+                                "< \"%s\" > \"%s\" 2>&1%s",
+                                SYSTEMQUOTE, backend_exec, boot_options,
                                 conns[i] * 5, conns[i],
-                                DEVNULL, DEVNULL);
+                                DEVNULL, DEVNULL, SYSTEMQUOTE);
                status = system(cmd);
                if (status == 0)
                        break;
@@ -852,12 +1055,12 @@ test_buffers(void)
        for (i = 0; i < len; i++)
        {
                snprintf(cmd, sizeof(cmd),
-                                "\"%s\" -boot -x0 %s "
+                                "%s\"%s\" -boot -x0 %s "
                                 "-c shared_buffers=%d -c max_connections=%d template1 "
-                                "<%s >%s 2>&1",
-                                backend_exec, boot_options,
+                                "< \"%s\" > \"%s\" 2>&1%s",
+                                SYSTEMQUOTE, backend_exec, boot_options,
                                 bufs[i], n_connections,
-                                DEVNULL, DEVNULL);
+                                DEVNULL, DEVNULL, SYSTEMQUOTE);
                status = system(cmd);
                if (status == 0)
                        break;
@@ -922,7 +1125,16 @@ setup_config(void)
                                                          "host    all         all         ::1",
                                                          "#host    all         all         ::1");
 #endif
-
+       
+       /* Replace default authentication methods */
+       conflines = replace_token(conflines,
+                                                        "@authmethod@",
+                                                         authmethod);
+       
+       conflines = replace_token(conflines,
+                                                         "@authcomment@",
+                                                         strcmp(authmethod,"trust") ? "" : authtrust_warning);
+               
        snprintf(path, sizeof(path), "%s/pg_hba.conf", pg_data);
 
        writefile(path, conflines);
@@ -1080,15 +1292,55 @@ get_set_pwd(void)
        char            pwdpath[MAXPGPATH];
        struct stat statbuf;
 
-       pwd1 = simple_prompt("Enter new superuser password: ", 100, false);
-       pwd2 = simple_prompt("Enter it again: ", 100, false);
-       if (strcmp(pwd1, pwd2) != 0)
+       if (pwprompt)
        {
-               fprintf(stderr, _("Passwords didn't match.\n"));
-               exit_nicely();
+               /*
+                * Read password from terminal
+                */
+               pwd1 = simple_prompt("Enter new superuser password: ", 100, false);
+               pwd2 = simple_prompt("Enter it again: ", 100, false);
+               if (strcmp(pwd1, pwd2) != 0)
+               {
+                       fprintf(stderr, _("Passwords didn't match.\n"));
+                       exit_nicely();
+               }
+               free(pwd2);
        }
-       free(pwd2);
+       else
+       {
+               /*
+                * Read password from file
+                *
+                * Ideally this should insist that the file not be world-readable.
+                * However, this option is mainly intended for use on Windows where
+                * file permissions may not exist at all, so we'll skip the paranoia
+                * for now.
+                */
+               FILE *pwf = fopen(pwfilename,"r");
+               char pwdbuf[MAXPGPATH];
+               int  i;
 
+               if (!pwf)
+               {
+                       fprintf(stderr, _("%s: could not open file \"%s\" for reading: %s\n"),
+                                       progname, pwfilename, strerror(errno));
+                       exit_nicely();
+               }
+               if (!fgets(pwdbuf, sizeof(pwdbuf), pwf))
+               {
+                       fprintf(stderr, _("%s: could not read password from file \"%s\": %s\n"),
+                                       progname, pwfilename, strerror(errno));
+                       exit_nicely();
+               }
+               fclose(pwf);
+
+               i = strlen(pwdbuf);
+               while (i > 0 && (pwdbuf[i-1] == '\r' || pwdbuf[i-1] == '\n'))
+                       pwdbuf[--i] = '\0';
+               
+               pwd1 = xstrdup(pwdbuf);
+               
+       }
        printf(_("setting password ... "));
        fflush(stdout);
 
@@ -1100,7 +1352,7 @@ get_set_pwd(void)
        PG_CMD_OPEN;
 
        if (fprintf(pg,
-                 "ALTER USER \"%s\" WITH PASSWORD '%s';\n", username, pwd1) < 0)
+                 "ALTER USER \"%s\" WITH PASSWORD '%s';\n", effective_user, pwd1) < 0)
        {
                /* write failure */
                exit_nicely();
@@ -1396,7 +1648,7 @@ setup_privileges(void)
        PG_CMD_OPEN;
 
        priv_lines = replace_token(privileges_setup,
-                                                          "$POSTGRES_SUPERUSERNAME", username);
+                                                          "$POSTGRES_SUPERUSERNAME", effective_user);
        for (line = priv_lines; *line != NULL; line++)
                PG_CMD_PUTLINE;
 
@@ -1739,8 +1991,10 @@ usage(const char *progname)
                         "                            in the respective category (default taken from\n"
                         "                            environment)\n"));
        printf(_("  --no-locale               equivalent to --locale=C\n"));
+       printf(_("  -A, --auth=method         default authentication method for local connections\n"));
        printf(_("  -U, --username=NAME       database superuser name\n"));
        printf(_("  -W, --pwprompt            prompt for a password for the new superuser\n"));
+       printf(_("  --pwfile=filename         read password for the new superuser from file\n"));
        printf(_("  -?, --help                show this help, then exit\n"));
        printf(_("  -V, --version             output version information, then exit\n"));
        printf(_("\nLess commonly used options:\n"));
@@ -1753,20 +2007,6 @@ usage(const char *progname)
        printf(_("\nReport bugs to <pgsql-bugs@postgresql.org>.\n"));
 }
 
-/*
- * Initialized NLS if enabled.
- */
-static void
-init_nls(void)
-{
-#ifdef ENABLE_NLS
-        setlocale(LC_ALL, "");
-        bindtextdomain("initdb", LOCALEDIR);
-        textdomain("initdb");
-#endif
-}
-
-
 int
 main(int argc, char *argv[])
 {
@@ -1785,7 +2025,9 @@ main(int argc, char *argv[])
                {"lc-time", required_argument, NULL, 6},
                {"lc-messages", required_argument, NULL, 7},
                {"no-locale", no_argument, NULL, 8},
+               {"auth", required_argument, NULL, 'A'}, 
                {"pwprompt", no_argument, NULL, 'W'},
+               {"pwfile", required_argument, NULL, 9},
                {"username", required_argument, NULL, 'U'},
                {"help", no_argument, NULL, '?'},
                {"version", no_argument, NULL, 'V'},
@@ -1802,11 +2044,19 @@ main(int argc, char *argv[])
        char       *short_version;
        char       *pgdenv;                     /* PGDATA value got from sent to
                                                                 * environment */
-       char       *subdirs[] =
-       {"global", "pg_xlog", "pg_clog", "base", "base/1"};
-       init_nls();
+       static const char *subdirs[] = {
+               "global",
+               "pg_xlog",
+               "pg_xlog/archive_status",
+               "pg_clog",
+               "pg_subtrans",
+               "base",
+               "base/1",
+               "pg_tblspc"
+       };
 
        progname = get_progname(argv[0]);
+       set_pglocale_pgservice(argv[0], "initdb");
 
     if (argc > 1)
     {
@@ -1824,10 +2074,13 @@ main(int argc, char *argv[])
 
        /* process command-line options */
 
-       while ((c = getopt_long(argc, argv, "dD:E:L:nU:W", long_options, &option_index)) != -1)
+       while ((c = getopt_long(argc, argv, "dD:E:L:nU:WA:", long_options, &option_index)) != -1)
        {
                switch (c)
                {
+                       case 'A':
+                               authmethod = xstrdup(optarg);
+                               break;
                        case 'D':
                                pg_data = xstrdup(optarg);
                                break;
@@ -1849,7 +2102,7 @@ main(int argc, char *argv[])
                                printf(_("Running in noclean mode.  Mistakes will not be cleaned up.\n"));
                                break;
                        case 'L':
-                               datadir = xstrdup(optarg);
+                               share_path = xstrdup(optarg);
                                break;
                        case 1:
                                locale = xstrdup(optarg);
@@ -1875,6 +2128,9 @@ main(int argc, char *argv[])
                        case 8:
                                locale = "C";
                                break;
+                       case 9:
+                               pwfilename = xstrdup(optarg);
+                               break;
                        case 's':
                                show_setting = true;
                                break;
@@ -1900,6 +2156,49 @@ main(int argc, char *argv[])
                                progname);
        }
 
+       if (pwprompt && pwfilename)
+       {
+               fprintf(stderr, _("%s: you cannot specify both password prompt and password file\n"), progname);
+               exit(1);
+       }
+       
+       if (authmethod == NULL || !strlen(authmethod))
+       {
+               authwarning = _("\nWARNING: enabling \"trust\" authentication for local connections.\n"
+                                               "You can change this by editing pg_hba.conf or using the -A flag the\n"
+                                               "next time you run initdb.\n");
+               authmethod="trust";
+       }
+
+       if (strcmp(authmethod,"md5") &&
+               strcmp(authmethod,"ident") && 
+               strncmp(authmethod,"ident ",6) && /* ident with space = param */
+               strcmp(authmethod,"trust") &&
+#ifdef USE_PAM
+               strcmp(authmethod,"pam") &&
+               strncmp(authmethod,"pam ",4) && /* pam with space = param */
+#endif
+               strcmp(authmethod,"crypt") &&
+               strcmp(authmethod,"password")
+               )
+               /*
+                *      Kerberos methods not listed because they are not supported
+                *      over local connections and are rejected in hba.c
+                */
+       {
+               fprintf(stderr, _("%s: unknown authentication method \"%s\".\n"), progname, authmethod);
+               exit(1);
+       }
+
+       if ((!strcmp(authmethod,"md5") ||
+                !strcmp(authmethod,"crypt") ||
+                !strcmp(authmethod,"password")) &&
+                !(pwprompt || pwfilename))
+       {
+               fprintf(stderr, _("%s: you need to specify a password for the superuser to enable %s authentication.\n"), progname, authmethod);
+               exit(1);
+       }
+
        if (strlen(pg_data) == 0)
        {
                pgdenv = getenv("PGDATA");
@@ -1951,18 +2250,27 @@ main(int argc, char *argv[])
        }
 
        /* store binary directory */
-       strcpy(bindir, backend_exec);
-       *last_path_separator(bindir) = '\0';
-       
+       strcpy(bin_path, backend_exec);
+       *last_dir_separator(bin_path) = '\0';
+
+       if (!share_path)
+       {
+               share_path = xmalloc(MAXPGPATH);
+               get_share_path(backend_exec, share_path);
+       }
+
+       canonicalize_path(share_path);
+
        if ((short_version = get_short_version()) == NULL)
        {
                fprintf(stderr, _("%s: could not determine valid short version string\n"), progname);
                exit(1);
        }
 
-       effective_user = get_id();
-       if (!strlen(username))
-               username = effective_user;
+       if (strlen(username))
+               effective_user = username;
+       else
+               effective_user = get_id();
 
        if (strlen(encoding))
                encodingid = get_encoding_id(encoding);
@@ -1983,15 +2291,13 @@ main(int argc, char *argv[])
        {
                fprintf(stderr,
                                "VERSION=%s\n"
-                               "PGDATA=%s\ndatadir=%s\nPGPATH=%s\n"
-                               "ENCODING=%s\nENCODINGID=%s\n"
+                               "PGDATA=%s\nshare_path=%s\nPGPATH=%s\n"
                                "POSTGRES_SUPERUSERNAME=%s\nPOSTGRES_BKI=%s\n"
                                "POSTGRES_DESCR=%s\nPOSTGRESQL_CONF_SAMPLE=%s\n"
                                "PG_HBA_SAMPLE=%s\nPG_IDENT_SAMPLE=%s\n",
                                PG_VERSION,
-                               pg_data, datadir, bindir,
-                               encoding, encodingid,
-                               username, bki_file,
+                               pg_data, share_path, bin_path,
+                               effective_user, bki_file,
                                desc_file, conf_file,
                                hba_file, ident_file);
                if (show_setting)
@@ -2008,21 +2314,20 @@ main(int argc, char *argv[])
        check_input(features_file);
        check_input(system_views_file);
 
+       setlocales();
+
        printf(_("The files belonging to this database system will be owned "
                   "by user \"%s\".\n"
                   "This user must also own the server process.\n\n"),
                   effective_user);
 
-       setlocales();
-
        if (strcmp(lc_ctype, lc_collate) == 0 &&
                strcmp(lc_ctype, lc_time) == 0 &&
                strcmp(lc_ctype, lc_numeric) == 0 &&
                strcmp(lc_ctype, lc_monetary) == 0 &&
                strcmp(lc_ctype, lc_messages) == 0)
        {
-               printf(_("The database cluster will be initialized with locale %s.\n\n"),
-                          lc_ctype);
+               printf(_("The database cluster will be initialized with locale %s.\n"), lc_ctype);
        }
        else
        {
@@ -2032,7 +2337,7 @@ main(int argc, char *argv[])
                           "  MESSAGES: %s\n"
                           "  MONETARY: %s\n"
                           "  NUMERIC:  %s\n"
-                          "  TIME:     %s\n\n"),
+                          "  TIME:     %s\n"),
                           lc_collate,
                           lc_ctype,
                           lc_messages,
@@ -2041,6 +2346,34 @@ main(int argc, char *argv[])
                           lc_time);
        }
 
+#ifdef HAVE_LANGINFO_H
+       if (strcmp(lc_ctype, "C") != 0 && strcmp(lc_ctype, "POSIX") != 0)
+       {
+               if (strlen(encoding) == 0)
+               {
+                       int tmp;
+                       tmp = find_matching_encoding(lc_ctype);
+                       if (tmp == -1)
+                       {
+                               fprintf(stderr, _("%s: could not find suitable encoding for locale \"%s\"\n"), progname, lc_ctype);
+                               fprintf(stderr, _("Rerun %s with the -E option.\n"), progname);
+                               fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
+                               exit(1);
+                       }
+                       else
+                       {
+                               encodingid = encodingid_to_string(tmp);
+                               printf(_("The default database encoding has accordingly been set to %s.\n"), 
+                                          pg_encoding_to_char(tmp));
+                       }
+               }
+               else
+                       check_encodings_match(atoi(encodingid), lc_ctype);
+       }
+#endif /* HAVE_LANGINFO_H */
+
+       printf("\n");
+
        umask(077);
 
        /*
@@ -2151,13 +2484,13 @@ main(int argc, char *argv[])
        /* Bootstrap template1 */
        bootstrap_template1(short_version);
 
-       /* Make the per-database PGVERSION for template1 only after init'ing it */
+       /* Make the per-database PG_VERSION for template1 only after init'ing it */
        set_short_version(short_version, "base/1");
 
        /* Create the stuff we don't need to use bootstrap mode for */
 
        setup_shadow();
-       if (pwprompt)
+       if (pwprompt || pwfilename)
                get_set_pwd();
 
        unlimit_systables();
@@ -2178,12 +2511,15 @@ main(int argc, char *argv[])
 
        make_template0();
 
+       if (authwarning != NULL)
+               fprintf(stderr, authwarning);
+
        printf(_("\nSuccess. You can now start the database server using:\n\n"
                   "    %s%s%s/postmaster -D %s%s%s\n"
                   "or\n"
                   "    %s%s%s/pg_ctl -D %s%s%s -l logfile start\n\n"),
-                QUOTE_PATH, bindir, QUOTE_PATH, QUOTE_PATH, pg_data, QUOTE_PATH,
-               QUOTE_PATH, bindir, QUOTE_PATH, QUOTE_PATH, pg_data, QUOTE_PATH);
+                QUOTE_PATH, bin_path, QUOTE_PATH, QUOTE_PATH, pg_data, QUOTE_PATH,
+               QUOTE_PATH, bin_path, QUOTE_PATH, QUOTE_PATH, pg_data, QUOTE_PATH);
 
        return 0;
 }