]> 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 9762a856ff5fb587a90c8152fba6b870048d969e..cd830ecda7a6215baf255e72e363c63b77d54b2e 100644 (file)
  *
  * template0 is made just by copying the completed template1.
  *
- *
- * TODO:
- *      - clean up find_postgres code and return values
- *
  * Note:
  *      The program has some memory leakage - it isn't worth cleaning it up.
  *
@@ -41,8 +37,9 @@
  *
  * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
+ * Portions taken from FreeBSD.
  *
- * $Header: /cvsroot/pgsql/src/bin/initdb/initdb.c,v 1.8 2003/11/14 17:19:35 tgl Exp $
+ * $PostgreSQL: pgsql/src/bin/initdb/initdb.c,v 1.45 2004/08/01 05:59:13 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
 #include <unistd.h>
 #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"
@@ -64,17 +65,15 @@ int                 optreset;
 #endif
 
 
+#define _(x) gettext((x))
+
 /* version string we expect back from postgres */
 #define PG_VERSIONSTR "postgres (PostgreSQL) " PG_VERSION "\n"
 
 /*
  * 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      *bindir = PGBINDIR;
-char      *datadir = PGDATADIR;
+char           *share_path = NULL;
 
 /* values to be obtained from arguments */
 char      *pg_data = "";
@@ -88,16 +87,15 @@ char           *lc_time = "";
 char      *lc_messages = "";
 char      *username = "";
 bool           pwprompt = false;
+char       *pwfilename = NULL;
+char       *authmethod = "";
 bool           debug = false;
 bool           noclean = false;
-bool           show_help = false;
-bool           show_version = false;
 bool           show_setting = false;
 
 
 /* internal vars */
-char      *progname;
-char      *self_path;
+const char *progname;
 char      *postgres;
 char      *encodingid = "0";
 char      *bki_file;
@@ -112,13 +110,25 @@ char         *system_views_file;
 char      *effective_user;
 bool           testpath = true;
 bool           made_new_pgdata = false;
+bool           found_existing_pgdata = false;
 char           infoversion[100];
-bool           not_ok = false;
+bool           caught_signal = false;
+bool           output_failed = false;
 
 /* defaults */
 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
  *
@@ -130,54 +140,31 @@ static const char *boot_options = "-F";
 static const char *backend_options = "-F -O -c search_path=pg_catalog -c exit_on_error=true";
 
 
-/* platform specific path stuff */
-#if defined(__CYGWIN__) || defined(WIN32)
-#define EXE ".exe"
-#define DEVNULL "nul"
-#else
-#define EXE ""
-#define DEVNULL "/dev/null"
-#endif
-
-#ifdef WIN32
-#define PATHSEP ';'
-#else
-#define PATHSEP ':'
-#endif
-
-/* detected path to postgres and (we assume) friends */
-char      *pgpath;
+/* path to 'initdb' binary directory */
+char      bin_path[MAXPGPATH];
+char      backend_exec[MAXPGPATH];
 
-/* forward declare all our functions */
-static bool rmtree(char *, bool);
+static void *xmalloc(size_t size);
+static char *xstrdup(const char *s);
+static bool rmtree(char *path, bool rmtopdir);
+static char **replace_token(char **lines, char *token, char *replacement);
+static char **readfile(char *path);
+static void writefile(char *path, char **lines);
+static int mkdir_p(char *path, mode_t omode);
 static void exit_nicely(void);
-static void canonicalize_path(char *);
-#ifdef WIN32
-static char *expanded_path(char *);
-#else
-#define expanded_path(x) (x)
-#endif
-static char **readfile(char *);
-static void writefile(char *, char **);
 static char *get_id(void);
-static char *get_encoding_id(char *);
+static char *get_encoding_id(char *encoding_name);
 static char *get_short_version(void);
-static int     mkdir_p(char *, mode_t);
-static int     check_data_dir(void);
-static bool mkdatadir(char *);
-static bool chklocale(const char *);
-static void setlocales(void);
-static void set_input(char **, char *);
+static int check_data_dir(void);
+static bool mkdatadir(const char *subdir);
+static void set_input(char **dest, char *filename);
 static void check_input(char *path);
-static int     find_postgres(char *);
-static int     set_paths(void);
-static char **replace_token(char **, char *, char *);
-static void set_short_version(char *, char *);
+static void set_short_version(char *short_version, char *extrapath);
 static void set_null_conf(void);
-static void test_buffers(void);
 static void test_connections(void);
+static void test_buffers(void);
 static void setup_config(void);
-static void bootstrap_template1(char *);
+static void bootstrap_template1(char *short_version);
 static void setup_shadow(void);
 static void get_set_pwd(void);
 static void unlimit_systables(void);
@@ -190,11 +177,12 @@ static void set_info_version(void);
 static void setup_schema(void);
 static void vacuum_db(void);
 static void make_template0(void);
-static void usage(void);
-static void trapsig(int);
+static void trapsig(int signum);
 static void check_ok(void);
-static char *xstrdup(const char *);
-static void *xmalloc(size_t);
+static bool chklocale(const char *locale);
+static void setlocales(void);
+static void usage(const char *progname);
+
 
 /*
  * macros for running pipes to postgres
@@ -204,22 +192,23 @@ static void *xmalloc(size_t);
 
 #define PG_CMD_OPEN \
 do { \
-                 pg = popen(cmd,PG_BINARY_W); \
-                 if (pg == NULL)  \
-                       exit_nicely(); \
+       fflush(stdout); \
+       fflush(stderr); \
+       pg = popen(cmd, "w"); \
+       if (pg == NULL) \
+               exit_nicely(); \
 } while (0)
 
 #define PG_CMD_CLOSE \
 do { \
-                if ((pclose(pg) >> 8) & 0xff) \
-                       exit_nicely(); \
+       if (pclose_check(pg)) \
+               exit_nicely(); \
 } while (0)
 
 #define PG_CMD_PUTLINE \
 do { \
-                if (fputs(*line, pg) < 0) \
-                  exit_nicely(); \
-                fflush(pg); \
+       if (fputs(*line, pg) < 0 || fflush(pg) < 0) \
+               output_failed = true; \
 } while (0)
 
 #ifndef WIN32
@@ -242,7 +231,7 @@ xmalloc(size_t size)
        result = malloc(size);
        if (!result)
        {
-               fputs("malloc failure - bailing out\n", stderr);
+               fprintf(stderr, _("%s: out of memory\n"), progname);
                exit(1);
        }
        return result;
@@ -256,7 +245,7 @@ xstrdup(const char *s)
        result = strdup(s);
        if (!result)
        {
-               fputs("strdup failure - bailing out\n", stderr);
+               fprintf(stderr, _("%s: out of memory\n"), progname);
                exit(1);
        }
        return result;
@@ -286,31 +275,6 @@ rmtree(char *path, bool rmtopdir)
 }
 
 
-/*
- * make all paths look like unix, with forward slashes
- * also strip any trailing slash.
- *
- * The Windows command processor will accept suitably quoted paths
- * with forward slashes, but barfs badly with mixed forward and back
- * slashes. Removing the trailing slash on a path means we never get
- * ugly double slashes.  Don't remove a leading slash, though.
- */
-static void
-canonicalize_path(char *path)
-{
-       char       *p;
-
-       for (p = path; *p; p++)
-       {
-#ifdef WIN32
-               if (*p == '\\')
-                       *p = '/';
-#endif
-       }
-       if (p > path+1 && *--p == '/')
-               *p = '\0';
-}
-
 /*
  * make a copy of the array of lines, with token replaced by replacement
  * the first time it occurs on each line.
@@ -387,7 +351,8 @@ readfile(char *path)
 
        if ((infile = fopen(path, "r")) == NULL)
        {
-               fprintf(stderr, "could not read %s\n", path);
+               fprintf(stderr, _("%s: could not open file \"%s\" for reading: %s\n"),
+                               progname, path, strerror(errno));
                exit_nicely();
        }
 
@@ -442,10 +407,10 @@ writefile(char *path, char **lines)
        FILE       *out_file;
        char      **line;
 
-       ;
        if ((out_file = fopen(path, PG_BINARY_W)) == NULL)
        {
-               fprintf(stderr, "could not write %s\n", path);
+               fprintf(stderr, _("%s: could not open file \"%s\" for writing: %s\n"),
+                               progname, path, strerror(errno));
                exit_nicely();
        }
        for (line = lines; *line != NULL; line++)
@@ -510,7 +475,7 @@ mkdir_p(char *path, mode_t omode)
                else if (p[0] != '/')
                        continue;
                *p = '\0';
-               if (p[1] == '\0')
+               if (!last && p[1] == '\0')
                        last = 1;
                if (first)
                {
@@ -572,37 +537,40 @@ mkdir_p(char *path, mode_t omode)
 static void
 exit_nicely(void)
 {
-       fprintf(stderr, "%s: failed\n", progname);
+       fprintf(stderr, _("%s: failed\n"), progname);
 
        if (!noclean)
        {
                if (made_new_pgdata)
                {
-                       fprintf(stderr, "%s: removing data directory \"%s\"\n",
+                       fprintf(stderr, _("%s: removing data directory \"%s\"\n"),
                                        progname, pg_data);
                        if (!rmtree(pg_data, true))
-                               fprintf(stderr, "%s: failed\n", progname);
+                               fprintf(stderr, _("%s: failed\n"), progname);
                }
-               else
+               else if (found_existing_pgdata)
                {
                        fprintf(stderr,
-                                       "%s: removing contents of data directory \"%s\"\n",
+                                       _("%s: removing contents of data directory \"%s\"\n"),
                                        progname, pg_data);
                        if (!rmtree(pg_data, false))
-                               fprintf(stderr, "%s: failed\n", progname);
+                               fprintf(stderr, _("%s: failed\n"), progname);
                }
+               /* otherwise died during startup, do nothing! */
        }
        else
        {
-        fprintf(stderr,
-                               "%s: data directory \"%s\" not removed at user's request\n",
-                               progname, pg_data);
+               if (made_new_pgdata || found_existing_pgdata)
+                       fprintf(stderr,
+                                       _("%s: data directory \"%s\" not removed at user's request\n"),
+                                       progname, pg_data);
        }
+
        exit(1);
 }
 
 /*
- * find the current user using code lifted from pg_id.c
+ * find the current user
  *
  * on unix make sure it isn't really root
  */
@@ -620,10 +588,10 @@ get_id(void)
        if (!geteuid())                         /* 0 is root's uid */
        {
                fprintf(stderr,
-                               "%s: cannot be run as root\n"
+                               _("%s: cannot be run as root\n"
                                "Please log in (using, e.g., \"su\") as the "
                                "(unprivileged) user that will\n"
-                               "own the server process.\n",
+                               "own the server process.\n"),
                                progname);
                exit(1);
        }
@@ -646,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
  */
@@ -653,22 +630,205 @@ 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",
+       fprintf(stderr, _("%s: \"%s\" is not a valid server encoding name\n"),
                        progname, encoding_name ? encoding_name : "(null)");
        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
  */
@@ -751,10 +911,9 @@ 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;
-       int                     res;
 
        path = xmalloc(strlen(pg_data) + 2 +
                                   (subdir == NULL ? 0 : strlen(subdir)));
@@ -764,13 +923,7 @@ mkdatadir(char *subdir)
        else
                strcpy(path, pg_data);
 
-       res = mkdir(path, 0700);
-       if (res == 0)
-               return true;
-       else if (subdir == NULL || errno != ENOENT)
-               return false;
-       else
-               return !mkdir_p(path, 0700);
+       return (mkdir_p(path, 0700) == 0);
 }
 
 
@@ -780,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);
 }
 
 /*
@@ -795,198 +948,15 @@ check_input(char *path)
        if (stat(path, &statbuf) != 0 || !S_ISREG(statbuf.st_mode))
        {
                fprintf(stderr,
-                               "%s: file \"%s\" not found\n"
-                  "This means you have a corrupted installation or identified\n"
-                               "the wrong directory with the invocation option -L.\n",
+                               _("%s: file \"%s\" does not exist\n"
+                                 "This means you have a corrupted installation or identified\n"
+                                 "the wrong directory with the invocation option -L.\n"),
                                progname, path);
                exit(1);
        }
 
 }
 
-/*
- * TODO - clean this up and handle the errors properly
- * don't overkill
- */
-#define FIND_SUCCESS 0
-#define FIND_NOT_FOUND 1
-#define FIND_STAT_ERR 2
-#define FIND_NOT_REGFILE 3
-#define FIND_BAD_PERM 4
-#define FIND_EXEC_ERR 5
-#define FIND_WRONG_VERSION 6
-
-/*
- * see if there is a postgres executable in the given path, and giving the
- * right version number
- */
-static int
-find_postgres(char *path)
-{
-       char            fn[MAXPGPATH];
-       char            cmd[MAXPGPATH];
-       char            line[100];
-
-#ifndef WIN32
-       int                     permmask = S_IROTH | S_IXOTH;
-#endif
-
-       struct stat statbuf;
-       FILE       *pgver;
-       int                     plen = strlen(path);
-
-       if (plen > 0 && path[plen - 1] != '/')
-               snprintf(fn, sizeof(fn), "%s/postgres%s", path, EXE);
-       else
-               snprintf(fn, sizeof(fn), "%spostgres%s", path, EXE);
-
-       if (stat(fn, &statbuf) != 0)
-       {
-               if (errno == ENOENT)
-                       return FIND_NOT_FOUND;
-               else
-                       return FIND_STAT_ERR;
-       }
-       if (!S_ISREG(statbuf.st_mode))
-               return FIND_NOT_REGFILE;
-
-#ifndef WIN32
-
-       /*
-        * Only unix requires this test, on WIN32 an .exe file should be
-        * executable
-        */
-       if ((statbuf.st_mode & permmask) != permmask)
-               return FIND_BAD_PERM;
-#endif
-
-       snprintf(cmd, sizeof(cmd), "\"%s/postgres\" -V 2>%s", path, DEVNULL);
-
-       if ((pgver = popen(cmd, "r")) == NULL)
-               return FIND_EXEC_ERR;
-
-       if (fgets(line, sizeof(line), pgver) == NULL)
-               perror("fgets failure");
-
-       pclose(pgver);
-
-       if (strcmp(line, PG_VERSIONSTR) != 0)
-               return FIND_WRONG_VERSION;
-
-       return FIND_SUCCESS;
-}
-
-/*
- * Windows doesn't like relative paths to executables (other things work fine)
- * so we call its builtin function to expand them. Elsewhere this is a NOOP
- */
-#ifdef WIN32
-static char *
-expanded_path(char *path)
-{
-       char            abspath[MAXPGPATH];
-
-       if (_fullpath(abspath, path, sizeof(abspath)) == NULL)
-       {
-               perror("expanded path");
-               return path;
-       }
-       canonicalize_path(abspath);
-       return xstrdup(abspath);
-}
-#endif
-
-/*
- * set the paths pointing to postgres
- *
- * look for it in the same place we found this program, or in the environment
- * path, or in the configured bindir.
- * We do it in this order because during upgrades users might move
- * their trees to backup places, so the hard-wired bindir might be inaccurate.
- *
- * XXX this needs work, as its error handling is vastly inferior to the
- * shell-script version, in particular the case where a postgres executable
- * is failing
- */
-static int
-set_paths(void)
-{
-       if (testpath && !self_path)
-       {
-               char       *path,
-                                  *cursor;
-               int                     pathlen,
-                                       i,
-                                       pathsegs;
-               char      **pathbits;
-               char            buf[MAXPGPATH];
-               struct stat statbuf;
-
-               path = xstrdup(getenv("PATH"));
-               pathlen = strlen(path);
-
-               for (i = 0, pathsegs = 1; i < pathlen; i++)
-               {
-                       if (path[i] == PATHSEP)
-                               pathsegs++;
-               }
-
-               pathbits = (char **) xmalloc(pathsegs * sizeof(char *));
-               for (i = 0, pathsegs = 0, cursor = path; i <= pathlen; i++)
-               {
-                       if (path[i] == PATHSEP || path[i] == 0)
-                       {
-                               path[i] = 0;
-                               if (strlen(cursor) == 0)
-                               {
-                                       /* empty path segment means current directory */
-                                       pathbits[pathsegs] = xstrdup(".");
-                               }
-                               else
-                               {
-                                       canonicalize_path(cursor);
-                                       pathbits[pathsegs] = cursor;
-                               }
-                               pathsegs++;
-                               cursor = path + i + 1;
-                       }
-               }
-
-               for (i = 0; i < pathsegs; i++)
-               {
-                       snprintf(buf, sizeof(buf), "%s/%s%s", pathbits[i], progname, EXE);
-                       if (stat(buf, &statbuf) == 0 && S_ISREG(statbuf.st_mode))
-                       {
-                               self_path = pathbits[i];
-                               break;
-                       }
-               }
-       }
-
-       if (testpath && self_path &&
-               (find_postgres(expanded_path(self_path)) == 0))
-       {
-               /* we found postgres on out own path */
-               pgpath = expanded_path(self_path);
-       }
-       else
-       {
-               /* look in the hardcoded bindir */
-               int                     res;
-               char       *cbindir;
-
-               cbindir = xstrdup(bindir);
-               canonicalize_path(cbindir);
-               res = find_postgres(expanded_path(cbindir));
-               if (res == 0)
-                       pgpath = expanded_path(cbindir);
-               else
-                       return 1;
-       }
-
-       return 0;
-}
-
 /*
  * write out the PG_VERSION file in the data dir, or its subdirectory
  * if extrapath is not NULL
@@ -1008,8 +978,11 @@ set_short_version(char *short_version, char *extrapath)
                sprintf(path, "%s/%s/PG_VERSION", pg_data, extrapath);
        }
        version_file = fopen(path, PG_BINARY_W);
+       if (version_file == NULL)
+               exit_nicely();
        fprintf(version_file, "%s\n", short_version);
-       fclose(version_file);
+       if (fclose(version_file))
+               exit_nicely();
 }
 
 /*
@@ -1024,7 +997,8 @@ set_null_conf(void)
        path = xmalloc(strlen(pg_data) + 17);
        sprintf(path, "%s/postgresql.conf", pg_data);
        conf_file = fopen(path, PG_BINARY_W);
-       fclose(conf_file);
+       if (conf_file == NULL || fclose(conf_file))
+               exit_nicely();
 }
 
 /*
@@ -1039,18 +1013,18 @@ test_connections(void)
        int                     i,
                                status;
 
-       printf("selecting default max_connections ... ");
+       printf(_("selecting default max_connections ... "));
        fflush(stdout);
 
        for (i = 0; i < len; i++)
        {
                snprintf(cmd, sizeof(cmd),
-                                "\"%s/postgres\" -boot -x0 %s "
+                                "%s\"%s\" -boot -x0 %s "
                                 "-c shared_buffers=%d -c max_connections=%d template1 "
-                                "<%s >%s 2>&1",
-                                pgpath, 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;
@@ -1075,18 +1049,18 @@ test_buffers(void)
        int                     i,
                                status;
 
-       printf("selecting default shared_buffers ... ");
+       printf(_("selecting default shared_buffers ... "));
        fflush(stdout);
 
        for (i = 0; i < len; i++)
        {
                snprintf(cmd, sizeof(cmd),
-                                "\"%s/postgres\" -boot -x0 %s "
+                                "%s\"%s\" -boot -x0 %s "
                                 "-c shared_buffers=%d -c max_connections=%d template1 "
-                                "<%s >%s 2>&1",
-                                pgpath, 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;
@@ -1108,7 +1082,7 @@ setup_config(void)
        char            repltok[100];
        char            path[MAXPGPATH];
 
-       fputs("creating configuration files ... ", stdout);
+       fputs(_("creating configuration files ... "), stdout);
        fflush(stdout);
 
        /* postgresql.conf */
@@ -1151,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);
@@ -1186,7 +1169,7 @@ bootstrap_template1(char *short_version)
 
        PG_CMD_DECL;
 
-       printf("creating template1 database in %s/base/1 ... ", pg_data);
+       printf(_("creating template1 database in %s/base/1 ... "), pg_data);
        fflush(stdout);
 
        if (debug)
@@ -1202,9 +1185,9 @@ bootstrap_template1(char *short_version)
        if (strcmp(headerline, *bki_lines) != 0)
        {
                fprintf(stderr,
-                               "%s: input file \"%s\" does not belong to PostgreSQL %s\n"
+                               _("%s: input file \"%s\" does not belong to PostgreSQL %s\n"
                                "Check your installation or specify the correct path "
-                               "using the option -L.\n",
+                               "using the option -L.\n"),
                                progname, bki_file, PG_VERSION);
                exit_nicely();
 
@@ -1226,11 +1209,14 @@ bootstrap_template1(char *short_version)
        snprintf(cmd, sizeof(cmd), "LC_CTYPE=%s", lc_ctype);
        putenv(xstrdup(cmd));
 
-       putenv("LC_ALL");
+       unsetenv("LC_ALL");
+
+       /* Also ensure backend isn't confused by this environment var: */
+       unsetenv("PGCLIENTENCODING");
 
        snprintf(cmd, sizeof(cmd),
-                        "\"%s/postgres\" -boot -x1 %s %s template1",
-                        pgpath, boot_options, talkargs);
+                        "\"%s\" -boot -x1 %s %s template1",
+                        backend_exec, boot_options, talkargs);
 
        PG_CMD_OPEN;
 
@@ -1275,12 +1261,12 @@ setup_shadow(void)
 
        PG_CMD_DECL;
 
-       fputs("initializing pg_shadow ... ", stdout);
+       fputs(_("initializing pg_shadow ... "), stdout);
        fflush(stdout);
 
        snprintf(cmd, sizeof(cmd),
-                        "\"%s/postgres\" %s template1 >%s",
-                        pgpath, backend_options,
+                        "\"%s\" %s template1 >%s",
+                        backend_exec, backend_options,
                         DEVNULL);
 
        PG_CMD_OPEN;
@@ -1306,27 +1292,67 @@ 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;
 
-       printf("setting password ... ");
+               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);
 
        snprintf(cmd, sizeof(cmd),
-                        "\"%s/postgres\" %s template1 >%s",
-                        pgpath, backend_options,
+                        "\"%s\" %s template1 >%s",
+                        backend_exec, backend_options,
                         DEVNULL);
 
        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();
@@ -1339,8 +1365,8 @@ get_set_pwd(void)
        if (stat(pwdpath, &statbuf) != 0 || !S_ISREG(statbuf.st_mode))
        {
                fprintf(stderr,
-                               "%s: The password file was not generated. "
-                               "Please report this problem.\n",
+                               _("%s: The password file was not generated. "
+                               "Please report this problem.\n"),
                                progname);
                exit_nicely();
        }
@@ -1369,12 +1395,12 @@ unlimit_systables(void)
 
        PG_CMD_DECL;
 
-       fputs("enabling unlimited row size for system tables ... ", stdout);
+       fputs(_("enabling unlimited row size for system tables ... "), stdout);
        fflush(stdout);
 
        snprintf(cmd, sizeof(cmd),
-                        "\"%s/postgres\" %s template1 >%s",
-                        pgpath, backend_options,
+                        "\"%s\" %s template1 >%s",
+                        backend_exec, backend_options,
                         DEVNULL);
 
        PG_CMD_OPEN;
@@ -1442,12 +1468,12 @@ setup_depend(void)
 
        PG_CMD_DECL;
 
-       fputs("initializing pg_depend ... ", stdout);
+       fputs(_("initializing pg_depend ... "), stdout);
        fflush(stdout);
 
        snprintf(cmd, sizeof(cmd),
-                        "\"%s/postgres\" %s template1 >%s",
-                        pgpath, backend_options,
+                        "\"%s\" %s template1 >%s",
+                        backend_exec, backend_options,
                         DEVNULL);
 
        PG_CMD_OPEN;
@@ -1470,7 +1496,7 @@ setup_sysviews(void)
 
        char      **sysviews_setup;
 
-       fputs("creating system views ... ", stdout);
+       fputs(_("creating system views ... "), stdout);
        fflush(stdout);
 
        sysviews_setup = readfile(system_views_file);
@@ -1479,8 +1505,8 @@ setup_sysviews(void)
         * We use -N here to avoid backslashing stuff in system_views.sql
         */
        snprintf(cmd, sizeof(cmd),
-                        "\"%s/postgres\" %s -N template1 >%s",
-                        pgpath, backend_options,
+                        "\"%s\" %s -N template1 >%s",
+                        backend_exec, backend_options,
                         DEVNULL);
 
        PG_CMD_OPEN;
@@ -1507,12 +1533,12 @@ setup_description(void)
        PG_CMD_DECL_NOLINE;
        int                     fres;
 
-       fputs("loading pg_description ... ", stdout);
+       fputs(_("loading pg_description ... "), stdout);
        fflush(stdout);
 
        snprintf(cmd, sizeof(cmd),
-                        "\"%s/postgres\" %s template1 >%s",
-                        pgpath, backend_options,
+                        "\"%s\" %s template1 >%s",
+                        backend_exec, backend_options,
                         DEVNULL);
 
        PG_CMD_OPEN;
@@ -1555,12 +1581,12 @@ setup_conversion(void)
 
        char      **conv_lines;
 
-       fputs("creating conversions ... ", stdout);
+       fputs(_("creating conversions ... "), stdout);
        fflush(stdout);
 
        snprintf(cmd, sizeof(cmd),
-                        "\"%s/postgres\" %s template1 >%s",
-                        pgpath, backend_options,
+                        "\"%s\" %s template1 >%s",
+                        backend_exec, backend_options,
                         DEVNULL);
 
        PG_CMD_OPEN;
@@ -1611,18 +1637,18 @@ setup_privileges(void)
 
        char      **priv_lines;
 
-       fputs("setting privileges on built-in objects ... ", stdout);
+       fputs(_("setting privileges on built-in objects ... "), stdout);
        fflush(stdout);
 
        snprintf(cmd, sizeof(cmd),
-                        "\"%s/postgres\" %s template1 >%s",
-                        pgpath, backend_options,
+                        "\"%s\" %s template1 >%s",
+                        backend_exec, backend_options,
                         DEVNULL);
 
        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;
 
@@ -1669,7 +1695,7 @@ setup_schema(void)
        char      **lines;
        int                     fres;
 
-       fputs("creating information schema ... ", stdout);
+       fputs(_("creating information schema ... "), stdout);
        fflush(stdout);
 
        lines = readfile(info_schema_file);
@@ -1678,8 +1704,8 @@ setup_schema(void)
         * We use -N here to avoid backslashing stuff in information_schema.sql
         */
        snprintf(cmd, sizeof(cmd),
-                        "\"%s/postgres\" %s -N template1 >%s",
-                        pgpath, backend_options,
+                        "\"%s\" %s -N template1 >%s",
+                        backend_exec, backend_options,
                         DEVNULL);
 
        PG_CMD_OPEN;
@@ -1695,8 +1721,8 @@ setup_schema(void)
        PG_CMD_CLOSE;
 
        snprintf(cmd, sizeof(cmd),
-                        "\"%s/postgres\" %s template1 >%s",
-                        pgpath, backend_options,
+                        "\"%s\" %s template1 >%s",
+                        backend_exec, backend_options,
                         DEVNULL);
 
        PG_CMD_OPEN;
@@ -1731,12 +1757,12 @@ vacuum_db(void)
 {
        PG_CMD_DECL_NOLINE;
 
-       fputs("vacuuming database template1 ... ", stdout);
+       fputs(_("vacuuming database template1 ... "), stdout);
        fflush(stdout);
 
        snprintf(cmd, sizeof(cmd),
-                        "\"%s/postgres\" %s template1 >%s",
-                        pgpath, backend_options,
+                        "\"%s\" %s template1 >%s",
+                        backend_exec, backend_options,
                         DEVNULL);
 
        PG_CMD_OPEN;
@@ -1787,12 +1813,12 @@ make_template0(void)
 
        PG_CMD_DECL;
 
-       fputs("copying template1 to template0 ... ", stdout);
+       fputs(_("copying template1 to template0 ... "), stdout);
        fflush(stdout);
 
        snprintf(cmd, sizeof(cmd),
-                        "\"%s/postgres\" %s template1 >%s",
-                        pgpath, backend_options,
+                        "\"%s\" %s template1 >%s",
+                        backend_exec, backend_options,
                         DEVNULL);
 
        PG_CMD_OPEN;
@@ -1833,7 +1859,7 @@ trapsig(int signum)
 {
        /* handle systems that reset the handler, like Windows (grr) */
        pqsignal(signum, trapsig);
-       not_ok = true;
+       caught_signal = true;
 }
 
 /*
@@ -1842,15 +1868,20 @@ trapsig(int signum)
 static void
 check_ok()
 {
-       if (not_ok)
+       if (caught_signal)
        {
-               printf("Caught Signal.\n");
+               printf(_("caught signal\n"));
+               exit_nicely();
+       }
+       else if (output_failed)
+       {
+               printf(_("could not write to child process\n"));
                exit_nicely();
        }
        else
        {
-               /* no signal caught */
-               printf("ok\n");
+               /* all seems well */
+               printf(_("ok\n"));
        }
 }
 
@@ -1880,7 +1911,7 @@ chklocale(const char *locale)
 
        /* should we exit here? */
        if (!ret)
-               fprintf(stderr, "%s: invalid locale name \"%s\"\n", progname, locale);
+               fprintf(stderr, _("%s: invalid locale name \"%s\"\n"), progname, locale);
 
        return ret;
 }
@@ -1941,62 +1972,41 @@ setlocales(void)
 
 }
 
-/*
- * help text data
- *
- * Note: $CMDNAME is replaced by the right thing in usage()
- */
-char      *usage_text[] = {
-       "$CMDNAME initializes a PostgreSQL database cluster.\n",
-       "\n",
-       "Usage:\n",
-       "  $CMDNAME [OPTION]... [DATADIR]\n",
-       "\n",
-       "Options:\n",
-       " [-D, --pgdata=]DATADIR     location for this database cluster\n",
-       "  -E, --encoding=ENCODING   set default encoding for new databases\n",
-       "  --locale=LOCALE           initialize database cluster with given locale\n",
-       "  --lc-collate, --lc-ctype, --lc-messages=LOCALE\n",
-       "  --lc-monetary, --lc-numeric, --lc-time=LOCALE\n",
-       "                            initialize database cluster with given locale\n",
-       "                            in the respective category (default taken from\n",
-       "                            environment)\n",
-       "  --no-locale               equivalent to --locale=C\n",
-       "  -U, --username=NAME       database superuser name\n",
-       "  -W, --pwprompt            prompt for a password for the new superuser\n",
-       "  -?, --help                show this help, then exit\n",
-       "  -V, --version             output version information, then exit\n",
-       "\n",
-       "Less commonly used options: \n",
-       "  -d, --debug               generate lots of debugging output\n",
-       "  -s, --show                show internal settings\n",
-       "  -L DIRECTORY              where to find the input files\n",
-       "  -n, --noclean             do not clean up after errors\n",
-       "\n",
-       "If the data directory is not specified, the environment variable PGDATA\n",
-       "is used.\n",
-       "\n",
-       "Report bugs to <pgsql-bugs@postgresql.org>.\n",
-       NULL
-};
-
-
 /*
  * print help text
  */
 static void
-usage(void)
+usage(const char *progname)
 {
-       int                     i;
-       char      **newtext;
-
-       newtext = replace_token(usage_text, "$CMDNAME", progname);
-
-       for (i = 0; newtext[i]; i++)
-               fputs(newtext[i], stdout);              /* faster than printf */
+       printf(_("%s initializes a PostgreSQL database cluster.\n\n"), progname);
+       printf(_("Usage:\n"));
+       printf(_("  %s [OPTION]... [DATADIR]\n"), progname);
+       printf(_("\nOptions:\n"));
+       printf(_(" [-D, --pgdata=]DATADIR     location for this database cluster\n"));
+       printf(_("  -E, --encoding=ENCODING   set default encoding for new databases\n"));
+       printf(_("  --locale=LOCALE           initialize database cluster with given locale\n"));
+       printf(_("  --lc-collate, --lc-ctype, --lc-messages=LOCALE\n"
+                        "  --lc-monetary, --lc-numeric, --lc-time=LOCALE\n"
+                        "                            initialize database cluster with given locale\n"
+                        "                            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"));
+       printf(_("  -d, --debug               generate lots of debugging output\n"));
+       printf(_("  -s, --show                show internal settings\n"));
+       printf(_("  -L DIRECTORY              where to find the input files\n"));
+       printf(_("  -n, --noclean             do not clean up after errors\n"));
+       printf(_("\nIf the data directory is not specified, the environment variable PGDATA\n"
+                        "is used.\n"));
+       printf(_("\nReport bugs to <pgsql-bugs@postgresql.org>.\n"));
 }
 
-
 int
 main(int argc, char *argv[])
 {
@@ -2015,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'},
@@ -2026,65 +2038,49 @@ main(int argc, char *argv[])
        };
 
        int                     c,
-                               i;
+                               i,
+                               ret;
        int                     option_index;
        char       *short_version;
        char       *pgdenv;                     /* PGDATA value got from sent to
                                                                 * environment */
-       char       *subdirs[] =
-       {"global", "pg_xlog", "pg_clog", "base", "base/1"};
-       char       *lastsep;
-       char       *carg0;
-#if defined(__CYGWIN__) || defined(WIN32)
-       char       *exe;                        /* location of exe suffix in progname */
-#endif
-
-       setlocale(LC_ALL, "");
-
-       /* parse argv[0] - detect explicit path if there was one */
-       carg0 = xstrdup(argv[0]);
-       canonicalize_path(carg0);
-
-       lastsep = strrchr(carg0, '/');
-       progname = lastsep ? xstrdup(lastsep + 1) : carg0;
-
-#if defined(__CYGWIN__) || defined(WIN32)
-       if (strlen(progname) > 4 &&
-               (exe = progname + (strlen(progname) - 4)) &&
-               stricmp(exe, EXE) == 0)
-       {
-               /* strip .exe suffix, regardless of case */
-               *exe = '\0';
-       }
-#endif
+       static const char *subdirs[] = {
+               "global",
+               "pg_xlog",
+               "pg_xlog/archive_status",
+               "pg_clog",
+               "pg_subtrans",
+               "base",
+               "base/1",
+               "pg_tblspc"
+       };
 
-       if (lastsep)
-       {
-               self_path = carg0;
-               *lastsep = '\0';
-       }
-       else
-       {
-               /* no path known to ourselves from argv[0] */
-               self_path = NULL;
-       }
+       progname = get_progname(argv[0]);
+       set_pglocale_pgservice(argv[0], "initdb");
+
+    if (argc > 1)
+    {
+        if (strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-?") == 0)
+        {
+            usage(progname);
+            exit(0);
+        }
+        if (strcmp(argv[1], "--version") == 0 || strcmp(argv[1], "-V") == 0)
+        {
+            puts("initdb (PostgreSQL) " PG_VERSION);
+            exit(0);
+        }
+    }
 
        /* process command-line options */
 
-       while (1)
+       while ((c = getopt_long(argc, argv, "dD:E:L:nU:WA:", long_options, &option_index)) != -1)
        {
-               /*
-                * a : as the first option char here lets us use ? as a short
-                * option
-                */
-               c = getopt_long(argc, argv, ":D:E:WU:?sVdnL:",
-                                               long_options, &option_index);
-
-               if (c == -1)
-                       break;
-
                switch (c)
                {
+                       case 'A':
+                               authmethod = xstrdup(optarg);
+                               break;
                        case 'D':
                                pg_data = xstrdup(optarg);
                                break;
@@ -2099,14 +2095,14 @@ main(int argc, char *argv[])
                                break;
                        case 'd':
                                debug = true;
-                printf("Running in debug mode.\n");
+                printf(_("Running in debug mode.\n"));
                                break;
                        case 'n':
                                noclean = true;
-                               printf("Running in noclean mode.  Mistakes will not be cleaned up.\n");
+                               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);
@@ -2132,20 +2128,17 @@ main(int argc, char *argv[])
                        case 8:
                                locale = "C";
                                break;
-                       case '?':
-                               show_help = true;
+                       case 9:
+                               pwfilename = xstrdup(optarg);
                                break;
                        case 's':
                                show_setting = true;
                                break;
-                       case 'V':
-                               show_version = true;
-                               break;
                        default:
-                               show_help = true;
-                               printf("Unrecognized option: %c\n", c);
+                               fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
+                        progname);
+                               exit(1);
                }
-
        }
 
        /* Non-option argument specifies data directory */
@@ -2156,19 +2149,54 @@ main(int argc, char *argv[])
        }
 
        if (optind < argc)
-               show_help = true;
+       {
+               fprintf(stderr, _("%s: too many command-line arguments (first is \"%s\")\n"),
+                                                 progname, argv[optind + 1]);
+               fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
+                               progname);
+       }
 
-       if (show_version)
+       if (pwprompt && pwfilename)
        {
-               /* hard coded name here, in case they rename executable */
-               printf("initdb (PostgreSQL) %s\n", PG_VERSION);
-               exit(0);
+               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 (show_help)
+       if ((!strcmp(authmethod,"md5") ||
+                !strcmp(authmethod,"crypt") ||
+                !strcmp(authmethod,"password")) &&
+                !(pwprompt || pwfilename))
        {
-               usage();
-               exit(0);
+               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)
@@ -2182,12 +2210,10 @@ main(int argc, char *argv[])
                else
                {
                        fprintf(stderr,
-                                       "%s: no data directory specified\n"
-                                       "You must identify the directory where the data "
-                                       "for this database system\n"
-                                       "will reside.  Do this with either the invocation "
-                                       "option -D or the\n"
-                                       "environment variable PGDATA.\n",
+                                       _("%s: no data directory specified\n"
+                                         "You must identify the directory where the data for this database system\n"
+                                         "will reside.  Do this with either the invocation option -D or the\n"
+                                         "environment variable PGDATA.\n"),
                                        progname);
                        exit(1);
                }
@@ -2205,25 +2231,46 @@ main(int argc, char *argv[])
        sprintf(pgdenv, "PGDATA=%s", pg_data);
        putenv(pgdenv);
 
-       if (set_paths() != 0)
+       if ((ret = find_other_exec(argv[0], "postgres", PG_VERSIONSTR,
+                                                          backend_exec)) < 0)
        {
-               fprintf(stderr,
-                               "The program \"postgres\" is needed by %s "
-                               "but was not found in \n"
-                               "the directory \"%s\". Check your installation.\n",
-                               progname, bindir);
+               if (ret == -1)
+                       fprintf(stderr,
+                                               _("The program \"postgres\" is needed by %s "
+                                               "but was not found in the same directory as \"%s\".\n"
+                                               "Check your installation.\n"),
+                                               progname, progname);
+               else
+                       fprintf(stderr,
+                                               _("The program \"postgres\" was found by %s "
+                                               "but was not the same version as \"%s\".\n"
+                                               "Check your installation.\n"),
+                                               progname, progname);
                exit(1);
        }
 
+       /* store binary directory */
+       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 get valid short version\n", progname);
+               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);
@@ -2244,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, pgpath,
-                               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)
@@ -2269,31 +2314,30 @@ main(int argc, char *argv[])
        check_input(features_file);
        check_input(system_views_file);
 
-       printf("The files belonging to this database system will be owned "
+       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",
+                  "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
        {
-               printf("The database cluster will be initialized with locales\n"
+               printf(_("The database cluster will be initialized with locales\n"
                           "  COLLATE:  %s\n"
                           "  CTYPE:    %s\n"
                           "  MESSAGES: %s\n"
                           "  MONETARY: %s\n"
                           "  NUMERIC:  %s\n"
-                          "  TIME:     %s\n\n",
+                          "  TIME:     %s\n"),
                           lc_collate,
                           lc_ctype,
                           lc_messages,
@@ -2302,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);
 
        /*
@@ -2323,11 +2395,16 @@ main(int argc, char *argv[])
        pqsignal(SIGTERM, trapsig);
 #endif
 
+       /* Ignore SIGPIPE when writing to backend, so we can clean up */
+#ifdef SIGPIPE
+       pqsignal(SIGPIPE, SIG_IGN);
+#endif
+
        switch (check_data_dir())
        {
                case 0:
                        /* PGDATA not there, must create it */
-                       printf("creating directory %s ... ",
+                       printf(_("creating directory %s ... "),
                                   pg_data);
                        fflush(stdout);
 
@@ -2341,43 +2418,42 @@ main(int argc, char *argv[])
 
                case 1:
                        /* Present but empty, fix permissions and use it */
-                       printf("fixing permissions on existing directory %s ... ",
+                       printf(_("fixing permissions on existing directory %s ... "),
                                   pg_data);
                        fflush(stdout);
 
                        if (chmod(pg_data, 0700) != 0)
                        {
                                perror(pg_data);
-                               /* don't exit_nicely(), it'll try to remove pg_data contents */
-                               exit(1);
+                               exit_nicely();
                        }
                        else
                                check_ok();
+
+                       found_existing_pgdata = true;
                        break;
 
                case 2:
                        /* Present and not empty */
                        fprintf(stderr,
-                                       "%s: directory \"%s\" exists but is not empty\n"
+                                       _("%s: directory \"%s\" exists but is not empty\n"
                                        "If you want to create a new database system, either remove or empty\n"
                                        "the directory \"%s\" or run %s\n"
-                                       "with an argument other than \"%s\".\n",
+                                       "with an argument other than \"%s\".\n"),
                                        progname, pg_data, pg_data, progname, pg_data);
-                       /* don't exit_nicely(), it'll try to remove pg_data contents */
-                       exit(1);
+                       exit(1);                        /* no further message needed */
 
                default:
                        /* Trouble accessing directory */
                        perror(pg_data);
-                       /* don't exit_nicely(), it'll try to remove pg_data contents */
-                       exit(1);
+                       exit_nicely();
        }
 
        /* Create required subdirectories */
 
        for (i = 0; i < (sizeof(subdirs) / sizeof(char *)); i++)
        {
-               printf("creating directory %s/%s ... ", pg_data, subdirs[i]);
+               printf(_("creating directory %s/%s ... "), pg_data, subdirs[i]);
                fflush(stdout);
 
                if (!mkdatadir(subdirs[i]))
@@ -2408,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();
@@ -2435,12 +2511,15 @@ main(int argc, char *argv[])
 
        make_template0();
 
-       printf("\nSuccess. You can now start the database server using:\n\n"
+       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, pgpath, QUOTE_PATH, QUOTE_PATH, pg_data, QUOTE_PATH,
-               QUOTE_PATH, pgpath, QUOTE_PATH, QUOTE_PATH, pg_data, QUOTE_PATH);
+                  "    %s%s%s/pg_ctl -D %s%s%s -l logfile start\n\n"),
+                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;
 }