]> 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 8b4ac1e29e70a2260c3655822caecd1d1fc065e3..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.41 2004/07/01 00:51:36 tgl 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"
@@ -85,6 +88,7 @@ char     *lc_messages = "";
 char      *username = "";
 bool           pwprompt = false;
 char       *pwfilename = NULL;
+char       *authmethod = "";
 bool           debug = false;
 bool           noclean = false;
 bool           show_setting = false;
@@ -115,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
  *
@@ -142,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);
@@ -600,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
  */
@@ -607,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"),
@@ -623,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
  */
@@ -705,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;
 
@@ -919,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);
@@ -1137,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();
@@ -1433,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;
 
@@ -1776,6 +1991,7 @@ 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"));
@@ -1809,6 +2025,7 @@ 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'},
@@ -1827,8 +2044,16 @@ main(int argc, char *argv[])
        char       *short_version;
        char       *pgdenv;                     /* PGDATA value got from sent to
                                                                 * environment */
-       char       *subdirs[] =
-       {"global", "pg_xlog", "pg_clog", "pg_subtrans", "base", "base/1", "pg_tblspc"};
+       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");
@@ -1849,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;
@@ -1933,6 +2161,43 @@ main(int argc, char *argv[])
                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)
        {
@@ -2002,9 +2267,10 @@ main(int argc, char *argv[])
                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);
@@ -2026,14 +2292,12 @@ main(int argc, char *argv[])
                fprintf(stderr,
                                "VERSION=%s\n"
                                "PGDATA=%s\nshare_path=%s\nPGPATH=%s\n"
-                               "ENCODING=%s\nENCODINGID=%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, share_path, bin_path,
-                               encoding, encodingid,
-                               username, bki_file,
+                               effective_user, bki_file,
                                desc_file, conf_file,
                                hba_file, ident_file);
                if (show_setting)
@@ -2050,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
        {
@@ -2074,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,
@@ -2083,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);
 
        /*
@@ -2220,6 +2511,9 @@ 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"