1 /*-------------------------------------------------------------------------
3 * initdb --- initialize a PostgreSQL installation
5 * initdb creates (initializes) a PostgreSQL database cluster (site,
6 * instance, installation, whatever). A database cluster is a
7 * collection of PostgreSQL databases all managed by the same postmaster.
9 * To create the database cluster, we create the directory that contains
10 * all its data, create the files that hold the global tables, create
11 * a few other control files for it, and create two databases: the
12 * template0 and template1 databases.
14 * The template databases are ordinary PostgreSQL databases. template0
15 * is never supposed to change after initdb, whereas template1 can be
16 * changed to add site-local standard data. Either one can be copied
17 * to produce a new database.
19 * To create template1, we run the postgres (backend) program in bootstrap
20 * mode and feed it data from the postgres.bki library file. After this
21 * initial bootstrap phase, some additional stuff is created by normal
22 * SQL commands fed to a standalone backend. Some of those commands are
23 * just embedded into this program (yeah, it's ugly), but larger chunks
24 * are taken from script files.
26 * template0 is made just by copying the completed template1.
29 * The program has some memory leakage - it isn't worth cleaning it up.
32 * This is a C implementation of the previous shell script for setting up a
33 * PostgreSQL cluster location, and should be highly compatible with it.
34 * author of C translation: Andrew Dunstan mailto:andrew@dunslane.net
36 * This code is released under the terms of the PostgreSQL License.
38 * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
39 * Portions Copyright (c) 1994, Regents of the University of California
40 * Portions taken from FreeBSD.
42 * $PostgreSQL: pgsql/src/bin/initdb/initdb.c,v 1.75 2005/02/22 04:38:22 momjian Exp $
44 *-------------------------------------------------------------------------
47 #include "postgres_fe.h"
55 #ifdef HAVE_LANGINFO_H
59 #include "libpq/pqsignal.h"
60 #include "mb/pg_wchar.h"
61 #include "getopt_long.h"
63 #ifndef HAVE_INT_OPTRESET
68 /* version string we expect back from postgres */
69 #define PG_VERSIONSTR "postgres (PostgreSQL) " PG_VERSION "\n"
72 * these values are passed in by makefile defines
74 char *share_path = NULL;
76 /* values to be obtained from arguments */
80 char *lc_collate = "";
82 char *lc_monetary = "";
83 char *lc_numeric = "";
85 char *lc_messages = "";
87 bool pwprompt = false;
88 char *pwfilename = NULL;
89 char *authmethod = "";
92 bool show_setting = false;
98 char *encodingid = "0";
104 char *conversion_file;
105 char *info_schema_file;
107 char *system_views_file;
108 char *effective_user;
109 bool testpath = true;
110 bool made_new_pgdata = false;
111 bool found_existing_pgdata = false;
112 char infoversion[100];
113 bool caught_signal = false;
114 bool output_failed = false;
115 int output_errno = 0;
118 int n_connections = 10;
122 * Warning messages for authentication methods
124 char *authtrust_warning = \
125 "# CAUTION: Configuring the system for local \"trust\" authentication allows\n"
126 "# any local user to connect as any PostgreSQL user, including the database\n"
127 "# superuser. If you do not trust all your local users, use another\n"
128 "# authentication method.\n";
129 char *authwarning = NULL;
132 * Centralized knowledge of switches to pass to backend
134 * Note: in the shell-script version, we also passed PGDATA as a -D switch,
135 * but here it is more convenient to pass it as an environment variable
136 * (no quoting to worry about).
138 static const char *boot_options = "-F";
139 static const char *backend_options = "-F -O -c search_path=pg_catalog -c exit_on_error=true";
142 /* path to 'initdb' binary directory */
143 char bin_path[MAXPGPATH];
144 char backend_exec[MAXPGPATH];
146 static void *xmalloc(size_t size);
147 static char *xstrdup(const char *s);
148 static char **replace_token(char **lines,
149 const char *token, const char *replacement);
150 #ifndef HAVE_UNIX_SOCKETS
151 static char **filter_lines_with_token(char **lines, const char *token);
153 static char **readfile(char *path);
154 static void writefile(char *path, char **lines);
155 static FILE *popen_check(const char *command, const char *mode);
156 static int mkdir_p(char *path, mode_t omode);
157 static void exit_nicely(void);
158 static char *get_id(void);
159 static char *get_encoding_id(char *encoding_name);
160 static char *get_short_version(void);
161 static int check_data_dir(void);
162 static bool mkdatadir(const char *subdir);
163 static void set_input(char **dest, char *filename);
164 static void check_input(char *path);
165 static void set_short_version(char *short_version, char *extrapath);
166 static void set_null_conf(void);
167 static void test_connections(void);
168 static void test_buffers(void);
169 static void setup_config(void);
170 static void bootstrap_template1(char *short_version);
171 static void setup_shadow(void);
172 static void get_set_pwd(void);
173 static void unlimit_systables(void);
174 static void setup_depend(void);
175 static void setup_sysviews(void);
176 static void setup_description(void);
177 static void setup_conversion(void);
178 static void setup_privileges(void);
179 static void set_info_version(void);
180 static void setup_schema(void);
181 static void vacuum_db(void);
182 static void make_template0(void);
183 static void trapsig(int signum);
184 static void check_ok(void);
185 static char *escape_quotes(const char *src);
186 static bool chklocale(const char *locale);
187 static void setlocales(void);
188 static void usage(const char *progname);
192 * macros for running pipes to postgres
194 #define PG_CMD_DECL char cmd[MAXPGPATH]; FILE *cmdfd
196 #define PG_CMD_OPEN \
198 cmdfd = popen_check(cmd, "w"); \
200 exit_nicely(); /* message already printed by popen_check */ \
203 #define PG_CMD_CLOSE \
205 if (pclose_check(cmdfd)) \
206 exit_nicely(); /* message already printed by pclose_check */ \
209 #define PG_CMD_PUTS(line) \
211 if (fputs(line, cmdfd) < 0 || fflush(cmdfd) < 0) \
212 output_failed = true, output_errno = errno; \
215 #define PG_CMD_PRINTF1(fmt, arg1) \
217 if (fprintf(cmdfd, fmt, arg1) < 0 || fflush(cmdfd) < 0) \
218 output_failed = true, output_errno = errno; \
221 #define PG_CMD_PRINTF2(fmt, arg1, arg2) \
223 if (fprintf(cmdfd, fmt, arg1, arg2) < 0 || fflush(cmdfd) < 0) \
224 output_failed = true, output_errno = errno; \
228 #define QUOTE_PATH ""
231 #define QUOTE_PATH "\""
236 * routines to check mem allocations and fail noisily.
238 * Note that we can't call exit_nicely() on a memory failure, as it calls
239 * rmtree() which needs memory allocation. So we just exit with a bang.
246 result = malloc(size);
249 fprintf(stderr, _("%s: out of memory\n"), progname);
256 xstrdup(const char *s)
263 fprintf(stderr, _("%s: out of memory\n"), progname);
270 * make a copy of the array of lines, with token replaced by replacement
271 * the first time it occurs on each line.
273 * This does most of what sed was used for in the shell script, but
274 * doesn't need any regexp stuff.
277 replace_token(char **lines, const char *token, const char *replacement)
286 for (i = 0; lines[i]; i++)
289 result = (char **) xmalloc(numlines * sizeof(char *));
291 toklen = strlen(token);
292 replen = strlen(replacement);
293 diff = replen - toklen;
295 for (i = 0; i < numlines; i++)
301 /* just copy pointer if NULL or no change needed */
302 if (lines[i] == NULL || (where = strstr(lines[i], token)) == NULL)
304 result[i] = lines[i];
308 /* if we get here a change is needed - set up new line */
310 newline = (char *) xmalloc(strlen(lines[i]) + diff + 1);
312 pre = where - lines[i];
314 strncpy(newline, lines[i], pre);
316 strcpy(newline + pre, replacement);
318 strcpy(newline + pre + replen, lines[i] + pre + toklen);
327 * make a copy of lines without any that contain the token
329 * a sort of poor man's grep -v
331 #ifndef HAVE_UNIX_SOCKETS
333 filter_lines_with_token(char **lines, const char *token)
339 for (i = 0; lines[i]; i++)
342 result = (char **) xmalloc(numlines * sizeof(char *));
344 for (src = 0, dst = 0; src < numlines; src++)
346 if (lines[src] == NULL || strstr(lines[src], token) == NULL)
347 result[dst++] = lines[src];
355 * get the lines from a text file
368 if ((infile = fopen(path, "r")) == NULL)
370 fprintf(stderr, _("%s: could not open file \"%s\" for reading: %s\n"),
371 progname, path, strerror(errno));
375 /* pass over the file twice - the first time to size the result */
377 while ((c = fgetc(infile)) != EOF)
383 if (linelen > maxlength)
389 /* handle last line without a terminating newline (yuck) */
393 if (linelen > maxlength)
396 /* set up the result and the line buffer */
398 result = (char **) xmalloc((nlines + 2) * sizeof(char *));
399 buffer = (char *) xmalloc(maxlength + 2);
401 /* now reprocess the file and store the lines */
405 while (fgets(buffer, maxlength + 1, infile) != NULL)
407 result[nlines] = xstrdup(buffer);
412 result[nlines] = NULL;
418 * write an array of lines to a file
420 * This is only used to write text files. Use fopen "w" not PG_BINARY_W
421 * so that the resulting configuration files are nicely editable on Windows.
424 writefile(char *path, char **lines)
429 if ((out_file = fopen(path, "w")) == NULL)
431 fprintf(stderr, _("%s: could not open file \"%s\" for writing: %s\n"),
432 progname, path, strerror(errno));
435 for (line = lines; *line != NULL; line++)
437 if (fputs(*line, out_file) < 0)
439 fprintf(stderr, _("%s: could not write file \"%s\": %s\n"),
440 progname, path, strerror(errno));
445 if (fclose(out_file))
447 fprintf(stderr, _("%s: could not write file \"%s\": %s\n"),
448 progname, path, strerror(errno));
454 * Open a subcommand with suitable error messaging
457 popen_check(const char *command, const char *mode)
464 cmdfd = popen(command, mode);
466 fprintf(stderr, _("%s: could not execute command \"%s\": %s\n"),
467 progname, command, strerror(errno));
471 /* source stolen from FreeBSD /src/bin/mkdir/mkdir.c and adapted */
474 * this tries to build all the elements of a path to a directory a la mkdir -p
475 * we assume the path is in canonical form, i.e. uses / as the separator
476 * we also assume it isn't null.
478 * note that on failure, the path arg has been modified to show the particular
479 * directory level we had problems with.
482 mkdir_p(char *path, mode_t omode)
497 /* skip network and drive specifiers for win32 */
500 if (p[0] == '/' && p[1] == '/')
503 p = strstr(p + 2, "/");
507 else if (p[1] == ':' &&
508 ((p[0] >= 'a' && p[0] <= 'z') ||
509 (p[0] >= 'A' && p[0] <= 'Z')))
517 if (p[0] == '/') /* Skip leading '/'. */
519 for (first = 1, last = 0; !last; ++p)
523 else if (p[0] != '/')
526 if (!last && p[1] == '\0')
531 * POSIX 1003.2: For each dir operand that does not name an
532 * existing directory, effects equivalent to those cased by
533 * the following command shall occcur:
535 * mkdir -p -m $(umask -S),u+wx $(dirname dir) && mkdir [-m mode]
538 * We change the user's umask and then restore it, instead of
542 numask = oumask & ~(S_IWUSR | S_IXUSR);
543 (void) umask(numask);
547 (void) umask(oumask);
549 /* check for pre-existing directory; ok if it's a parent */
550 if (stat(path, &sb) == 0)
552 if (!S_ISDIR(sb.st_mode))
562 else if (mkdir(path, last ? omode : S_IRWXU | S_IRWXG | S_IRWXO) < 0)
571 (void) umask(oumask);
576 * clean up any files we created on failure
577 * if we created the data directory remove it too
586 fprintf(stderr, _("%s: removing data directory \"%s\"\n"),
588 if (!rmtree(pg_data, true))
589 fprintf(stderr, _("%s: failed to remove data directory\n"),
592 else if (found_existing_pgdata)
595 _("%s: removing contents of data directory \"%s\"\n"),
597 if (!rmtree(pg_data, false))
598 fprintf(stderr, _("%s: failed to remove contents of data directory\n"),
601 /* otherwise died during startup, do nothing! */
605 if (made_new_pgdata || found_existing_pgdata)
607 _("%s: data directory \"%s\" not removed at user's request\n"),
615 * find the current user
617 * on unix make sure it isn't really root
626 pw = getpwuid(geteuid());
628 #ifndef __BEOS__ /* no root check on BEOS */
630 if (geteuid() == 0) /* 0 is root's uid */
633 _("%s: cannot be run as root\n"
634 "Please log in (using, e.g., \"su\") as the "
635 "(unprivileged) user that will\n"
636 "own the server process.\n"),
642 #else /* the windows code */
649 struct passwd_win32 *pw = &pass_win32;
650 DWORD pwname_size = sizeof(pass_win32.pw_name) - 1;
653 GetUserName(pw->pw_name, &pwname_size);
656 return xstrdup(pw->pw_name);
660 encodingid_to_string(int enc)
664 sprintf(result, "%d", enc);
665 return xstrdup(result);
669 * get the encoding id for a given encoding name
672 get_encoding_id(char *encoding_name)
676 if (encoding_name && *encoding_name)
678 if ((enc = pg_char_to_encoding(encoding_name)) >= 0 &&
679 pg_valid_server_encoding(encoding_name) >= 0)
680 return encodingid_to_string(enc);
682 fprintf(stderr, _("%s: \"%s\" is not a valid server encoding name\n"),
683 progname, encoding_name ? encoding_name : "(null)");
687 #if defined(HAVE_LANGINFO_H) && defined(CODESET)
689 * Checks whether the encoding selected for PostgreSQL and the
690 * encoding used by the system locale match.
693 struct encoding_match
695 enum pg_enc pg_enc_code;
696 char *system_enc_name;
699 struct encoding_match encoding_match_list[] = {
700 {PG_EUC_JP, "EUC-JP"},
701 {PG_EUC_JP, "eucJP"},
702 {PG_EUC_JP, "IBM-eucJP"},
703 {PG_EUC_JP, "sdeckanji"},
705 {PG_EUC_CN, "EUC-CN"},
706 {PG_EUC_CN, "eucCN"},
707 {PG_EUC_CN, "IBM-eucCN"},
708 {PG_EUC_CN, "GB2312"},
709 {PG_EUC_CN, "dechanzi"},
711 {PG_EUC_KR, "EUC-KR"},
712 {PG_EUC_KR, "eucKR"},
713 {PG_EUC_KR, "IBM-eucKR"},
714 {PG_EUC_KR, "deckorean"},
717 {PG_EUC_TW, "EUC-TW"},
718 {PG_EUC_TW, "eucTW"},
719 {PG_EUC_TW, "IBM-eucTW"},
720 {PG_EUC_TW, "cns11643"},
729 {PG_LATIN1, "ISO-8859-1"},
730 {PG_LATIN1, "ISO8859-1"},
731 {PG_LATIN1, "iso88591"},
733 {PG_LATIN2, "ISO-8859-2"},
734 {PG_LATIN2, "ISO8859-2"},
735 {PG_LATIN2, "iso88592"},
737 {PG_LATIN3, "ISO-8859-3"},
738 {PG_LATIN3, "ISO8859-3"},
739 {PG_LATIN3, "iso88593"},
741 {PG_LATIN4, "ISO-8859-4"},
742 {PG_LATIN4, "ISO8859-4"},
743 {PG_LATIN4, "iso88594"},
745 {PG_LATIN5, "ISO-8859-9"},
746 {PG_LATIN5, "ISO8859-9"},
747 {PG_LATIN5, "iso88599"},
749 {PG_LATIN6, "ISO-8859-10"},
750 {PG_LATIN6, "ISO8859-10"},
751 {PG_LATIN6, "iso885910"},
753 {PG_LATIN7, "ISO-8859-13"},
754 {PG_LATIN7, "ISO8859-13"},
755 {PG_LATIN7, "iso885913"},
757 {PG_LATIN8, "ISO-8859-14"},
758 {PG_LATIN8, "ISO8859-14"},
759 {PG_LATIN8, "iso885914"},
761 {PG_LATIN9, "ISO-8859-15"},
762 {PG_LATIN9, "ISO8859-15"},
763 {PG_LATIN9, "iso885915"},
765 {PG_LATIN10, "ISO-8859-16"},
766 {PG_LATIN10, "ISO8859-16"},
767 {PG_LATIN10, "iso885916"},
769 {PG_WIN1256, "CP1256"},
774 {PG_KOI8R, "KOI8-R"},
775 {PG_WIN1251, "CP1251"},
778 {PG_ISO_8859_5, "ISO-8859-5"},
779 {PG_ISO_8859_5, "ISO8859-5"},
780 {PG_ISO_8859_5, "iso88595"},
782 {PG_ISO_8859_6, "ISO-8859-6"},
783 {PG_ISO_8859_6, "ISO8859-6"},
784 {PG_ISO_8859_6, "iso88596"},
786 {PG_ISO_8859_7, "ISO-8859-7"},
787 {PG_ISO_8859_7, "ISO8859-7"},
788 {PG_ISO_8859_7, "iso88597"},
790 {PG_ISO_8859_8, "ISO-8859-8"},
791 {PG_ISO_8859_8, "ISO8859-8"},
792 {PG_ISO_8859_8, "iso88598"},
794 {PG_SQL_ASCII, NULL} /* end marker */
798 get_encoding_from_locale(const char *ctype)
803 save = setlocale(LC_CTYPE, NULL);
806 save = xstrdup(save);
808 setlocale(LC_CTYPE, ctype);
809 sys = nl_langinfo(CODESET);
812 setlocale(LC_CTYPE, save);
819 check_encodings_match(int pg_enc, const char *ctype)
824 sys = get_encoding_from_locale(ctype);
826 for (i = 0; encoding_match_list[i].system_enc_name; i++)
828 if (pg_enc == encoding_match_list[i].pg_enc_code
829 && strcasecmp(sys, encoding_match_list[i].system_enc_name) == 0)
837 _("%s: warning: encoding mismatch\n"), progname);
839 _("The encoding you selected (%s) and the encoding that the selected\n"
840 "locale uses (%s) are not known to match. This may lead to\n"
841 "misbehavior in various character string processing functions. To fix\n"
842 "this situation, rerun %s and either do not specify an encoding\n"
843 "explicitly, or choose a matching combination.\n"),
844 pg_encoding_to_char(pg_enc), sys, progname);
851 find_matching_encoding(const char *ctype)
856 sys = get_encoding_from_locale(ctype);
858 for (i = 0; encoding_match_list[i].system_enc_name; i++)
860 if (strcasecmp(sys, encoding_match_list[i].system_enc_name) == 0)
863 return encoding_match_list[i].pg_enc_code;
870 #endif /* HAVE_LANGINFO_H && CODESET */
873 * get short version of VERSION
876 get_short_version(void)
882 vr = xstrdup(PG_VERSION);
884 for (end = 0; vr[end] != '\0'; end++)
895 else if (vr[end] < '0' || vr[end] > '9')
897 /* gone past digits and dots */
901 if (end == 0 || vr[end - 1] == '.' || !gotdot)
909 * make sure the data directory either doesn't exist or is empty
911 * Returns 0 if nonexistent, 1 if exists and empty, 2 if not empty,
912 * or -1 if trouble accessing directory
923 chkdir = opendir(pg_data);
926 return (errno == ENOENT) ? 0 : -1;
928 while ((file = readdir(chkdir)) != NULL)
930 if (strcmp(".", file->d_name) == 0 || strcmp("..", file->d_name) == 0)
932 /* skip this and parent directory */
937 result = 2; /* not empty */
945 result = -1; /* some kind of I/O error? */
951 * make the data directory (or one of its subdirectories if subdir is not NULL)
954 mkdatadir(const char *subdir)
958 path = xmalloc(strlen(pg_data) + 2 +
959 (subdir == NULL ? 0 : strlen(subdir)));
962 sprintf(path, "%s/%s", pg_data, subdir);
964 strcpy(path, pg_data);
966 if (mkdir_p(path, 0700) == 0)
969 fprintf(stderr, _("%s: could not create directory \"%s\": %s\n"),
970 progname, path, strerror(errno));
977 * set name of given input file variable under data directory
980 set_input(char **dest, char *filename)
982 *dest = xmalloc(strlen(share_path) + strlen(filename) + 2);
983 sprintf(*dest, "%s/%s", share_path, filename);
987 * check that given input file exists
990 check_input(char *path)
994 if (stat(path, &statbuf) != 0 || !S_ISREG(statbuf.st_mode))
997 _("%s: file \"%s\" does not exist\n"
998 "This means you have a corrupted installation or identified\n"
999 "the wrong directory with the invocation option -L.\n"),
1006 * write out the PG_VERSION file in the data dir, or its subdirectory
1007 * if extrapath is not NULL
1010 set_short_version(char *short_version, char *extrapath)
1015 if (extrapath == NULL)
1017 path = xmalloc(strlen(pg_data) + 12);
1018 sprintf(path, "%s/PG_VERSION", pg_data);
1022 path = xmalloc(strlen(pg_data) + strlen(extrapath) + 13);
1023 sprintf(path, "%s/%s/PG_VERSION", pg_data, extrapath);
1025 version_file = fopen(path, PG_BINARY_W);
1026 if (version_file == NULL)
1028 fprintf(stderr, _("%s: could not open file \"%s\" for writing: %s\n"),
1029 progname, path, strerror(errno));
1032 if (fprintf(version_file, "%s\n", short_version) < 0 ||
1033 fclose(version_file))
1035 fprintf(stderr, _("%s: could not write file \"%s\": %s\n"),
1036 progname, path, strerror(errno));
1042 * set up an empty config file so we can check buffers and connections
1050 path = xmalloc(strlen(pg_data) + 17);
1051 sprintf(path, "%s/postgresql.conf", pg_data);
1052 conf_file = fopen(path, PG_BINARY_W);
1053 if (conf_file == NULL)
1055 fprintf(stderr, _("%s: could not open file \"%s\" for writing: %s\n"),
1056 progname, path, strerror(errno));
1059 if (fclose(conf_file))
1061 fprintf(stderr, _("%s: could not write file \"%s\": %s\n"),
1062 progname, path, strerror(errno));
1068 * check how many connections we can sustain
1071 test_connections(void)
1073 char cmd[MAXPGPATH];
1074 static const int conns[] = {100, 50, 40, 30, 20, 10};
1075 static const int len = sizeof(conns) / sizeof(int);
1079 printf(_("selecting default max_connections ... "));
1082 for (i = 0; i < len; i++)
1084 snprintf(cmd, sizeof(cmd),
1085 "%s\"%s\" -boot -x0 %s "
1086 "-c shared_buffers=%d -c max_connections=%d template1 "
1087 "< \"%s\" > \"%s\" 2>&1%s",
1088 SYSTEMQUOTE, backend_exec, boot_options,
1089 conns[i] * 5, conns[i],
1090 DEVNULL, DEVNULL, SYSTEMQUOTE);
1091 status = system(cmd);
1097 n_connections = conns[i];
1099 printf("%d\n", n_connections);
1103 * check how many buffers we can run with
1108 char cmd[MAXPGPATH];
1109 static const int bufs[] = {1000, 900, 800, 700, 600, 500,
1110 400, 300, 200, 100, 50};
1111 static const int len = sizeof(bufs) / sizeof(int);
1115 printf(_("selecting default shared_buffers ... "));
1118 for (i = 0; i < len; i++)
1120 snprintf(cmd, sizeof(cmd),
1121 "%s\"%s\" -boot -x0 %s "
1122 "-c shared_buffers=%d -c max_connections=%d template1 "
1123 "< \"%s\" > \"%s\" 2>&1%s",
1124 SYSTEMQUOTE, backend_exec, boot_options,
1125 bufs[i], n_connections,
1126 DEVNULL, DEVNULL, SYSTEMQUOTE);
1127 status = system(cmd);
1133 n_buffers = bufs[i];
1135 printf("%d\n", n_buffers);
1139 * set up all the config files
1146 char path[MAXPGPATH];
1148 fputs(_("creating configuration files ... "), stdout);
1151 /* postgresql.conf */
1153 conflines = readfile(conf_file);
1155 snprintf(repltok, sizeof(repltok), "max_connections = %d", n_connections);
1156 conflines = replace_token(conflines, "#max_connections = 100", repltok);
1158 snprintf(repltok, sizeof(repltok), "shared_buffers = %d", n_buffers);
1159 conflines = replace_token(conflines, "#shared_buffers = 1000", repltok);
1161 #if DEF_PGPORT != 5432
1162 snprintf(repltok, sizeof(repltok), "#port = %d", DEF_PGPORT);
1163 conflines = replace_token(conflines, "#port = 5432", repltok);
1166 lc_messages = escape_quotes(lc_messages);
1167 snprintf(repltok, sizeof(repltok), "lc_messages = '%s'", lc_messages);
1168 conflines = replace_token(conflines, "#lc_messages = 'C'", repltok);
1170 lc_monetary = escape_quotes(lc_monetary);
1171 snprintf(repltok, sizeof(repltok), "lc_monetary = '%s'", lc_monetary);
1172 conflines = replace_token(conflines, "#lc_monetary = 'C'", repltok);
1174 lc_numeric = escape_quotes(lc_numeric);
1175 snprintf(repltok, sizeof(repltok), "lc_numeric = '%s'", lc_numeric);
1176 conflines = replace_token(conflines, "#lc_numeric = 'C'", repltok);
1178 lc_time = escape_quotes(lc_time);
1179 snprintf(repltok, sizeof(repltok), "lc_time = '%s'", lc_time);
1180 conflines = replace_token(conflines, "#lc_time = 'C'", repltok);
1182 snprintf(path, sizeof(path), "%s/postgresql.conf", pg_data);
1184 writefile(path, conflines);
1192 conflines = readfile(hba_file);
1194 #ifndef HAVE_UNIX_SOCKETS
1195 conflines = filter_lines_with_token(conflines,"@remove-line-for-nolocal@");
1197 conflines = replace_token(conflines,"@remove-line-for-nolocal@","");
1201 conflines = replace_token(conflines,
1203 "#host all all ::1");
1206 /* Replace default authentication methods */
1207 conflines = replace_token(conflines,
1211 conflines = replace_token(conflines,
1213 strcmp(authmethod, "trust") ? "" : authtrust_warning);
1215 snprintf(path, sizeof(path), "%s/pg_hba.conf", pg_data);
1217 writefile(path, conflines);
1224 conflines = readfile(ident_file);
1226 snprintf(path, sizeof(path), "%s/pg_ident.conf", pg_data);
1228 writefile(path, conflines);
1238 * run the BKI script in bootstrap mode to create template1
1241 bootstrap_template1(char *short_version)
1245 char *talkargs = "";
1247 char headerline[MAXPGPATH];
1249 printf(_("creating template1 database in %s/base/1 ... "), pg_data);
1255 bki_lines = readfile(bki_file);
1257 /* Check that bki file appears to be of the right version */
1259 snprintf(headerline, sizeof(headerline), "# PostgreSQL %s\n",
1262 if (strcmp(headerline, *bki_lines) != 0)
1265 _("%s: input file \"%s\" does not belong to PostgreSQL %s\n"
1266 "Check your installation or specify the correct path "
1267 "using the option -L.\n"),
1268 progname, bki_file, PG_VERSION);
1272 bki_lines = replace_token(bki_lines, "POSTGRES", effective_user);
1274 bki_lines = replace_token(bki_lines, "ENCODING", encodingid);
1277 * Pass correct LC_xxx environment to bootstrap.
1279 * The shell script arranged to restore the LC settings afterwards, but
1280 * there doesn't seem to be any compelling reason to do that.
1282 snprintf(cmd, sizeof(cmd), "LC_COLLATE=%s", lc_collate);
1283 putenv(xstrdup(cmd));
1285 snprintf(cmd, sizeof(cmd), "LC_CTYPE=%s", lc_ctype);
1286 putenv(xstrdup(cmd));
1290 /* Also ensure backend isn't confused by this environment var: */
1291 unsetenv("PGCLIENTENCODING");
1293 snprintf(cmd, sizeof(cmd),
1294 "\"%s\" -boot -x1 %s %s template1",
1295 backend_exec, boot_options, talkargs);
1299 for (line = bki_lines; *line != NULL; line++)
1313 * set up the shadow password table
1320 static char *pg_shadow_setup[] = {
1322 * Create a trigger so that direct updates to pg_shadow will be
1323 * written to the flat password/group files pg_pwd and pg_group
1325 "CREATE TRIGGER pg_sync_pg_pwd "
1326 " AFTER INSERT OR UPDATE OR DELETE ON pg_shadow "
1327 " FOR EACH ROW EXECUTE PROCEDURE update_pg_pwd_and_pg_group();\n",
1328 "CREATE TRIGGER pg_sync_pg_group "
1329 " AFTER INSERT OR UPDATE OR DELETE ON pg_group "
1330 " FOR EACH ROW EXECUTE PROCEDURE update_pg_pwd_and_pg_group();\n",
1333 * needs to be done before alter user, because alter user checks
1334 * that pg_shadow is secure ...
1336 "REVOKE ALL on pg_shadow FROM public;\n",
1340 fputs(_("initializing pg_shadow ... "), stdout);
1343 snprintf(cmd, sizeof(cmd),
1344 "\"%s\" %s template1 >%s",
1345 backend_exec, backend_options,
1350 for (line = pg_shadow_setup; *line != NULL; line++)
1359 * get the superuser password if required, and call postgres to set it
1368 char pwdpath[MAXPGPATH];
1369 struct stat statbuf;
1374 * Read password from terminal
1376 pwd1 = simple_prompt("Enter new superuser password: ", 100, false);
1377 pwd2 = simple_prompt("Enter it again: ", 100, false);
1378 if (strcmp(pwd1, pwd2) != 0)
1380 fprintf(stderr, _("Passwords didn't match.\n"));
1388 * Read password from file
1390 * Ideally this should insist that the file not be world-readable.
1391 * However, this option is mainly intended for use on Windows
1392 * where file permissions may not exist at all, so we'll skip the
1395 FILE *pwf = fopen(pwfilename, "r");
1396 char pwdbuf[MAXPGPATH];
1401 fprintf(stderr, _("%s: could not open file \"%s\" for reading: %s\n"),
1402 progname, pwfilename, strerror(errno));
1405 if (!fgets(pwdbuf, sizeof(pwdbuf), pwf))
1407 fprintf(stderr, _("%s: could not read password from file \"%s\": %s\n"),
1408 progname, pwfilename, strerror(errno));
1414 while (i > 0 && (pwdbuf[i - 1] == '\r' || pwdbuf[i - 1] == '\n'))
1417 pwd1 = xstrdup(pwdbuf);
1420 printf(_("setting password ... "));
1423 snprintf(cmd, sizeof(cmd),
1424 "\"%s\" %s template1 >%s",
1425 backend_exec, backend_options,
1430 PG_CMD_PRINTF2("ALTER USER \"%s\" WITH PASSWORD '%s';\n",
1431 effective_user, pwd1);
1437 snprintf(pwdpath, sizeof(pwdpath), "%s/global/pg_pwd", pg_data);
1438 if (stat(pwdpath, &statbuf) != 0 || !S_ISREG(statbuf.st_mode))
1441 _("%s: The password file was not generated. "
1442 "Please report this problem.\n"),
1452 unlimit_systables(void)
1456 static char *systables_setup[] = {
1457 "ALTER TABLE pg_attrdef CREATE TOAST TABLE;\n",
1458 "ALTER TABLE pg_constraint CREATE TOAST TABLE;\n",
1459 "ALTER TABLE pg_database CREATE TOAST TABLE;\n",
1460 "ALTER TABLE pg_description CREATE TOAST TABLE;\n",
1461 "ALTER TABLE pg_group CREATE TOAST TABLE;\n",
1462 "ALTER TABLE pg_proc CREATE TOAST TABLE;\n",
1463 "ALTER TABLE pg_rewrite CREATE TOAST TABLE;\n",
1464 "ALTER TABLE pg_shadow CREATE TOAST TABLE;\n",
1465 "ALTER TABLE pg_statistic CREATE TOAST TABLE;\n",
1469 fputs(_("enabling unlimited row size for system tables ... "), stdout);
1472 snprintf(cmd, sizeof(cmd),
1473 "\"%s\" %s template1 >%s",
1474 backend_exec, backend_options,
1479 for (line = systables_setup; *line != NULL; line++)
1495 static char *pg_depend_setup[] = {
1497 * Make PIN entries in pg_depend for all objects made so far in
1498 * the tables that the dependency code handles. This is overkill
1499 * (the system doesn't really depend on having every last weird
1500 * datatype, for instance) but generating only the minimum
1501 * required set of dependencies seems hard.
1503 * Note that we deliberately do not pin the system views, which
1504 * haven't been created yet.
1506 * First delete any already-made entries; PINs override all else, and
1507 * must be the only entries for their objects.
1509 "DELETE FROM pg_depend;\n",
1510 "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' "
1511 " FROM pg_class;\n",
1512 "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' "
1514 "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' "
1516 "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' "
1518 "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' "
1519 " FROM pg_constraint;\n",
1520 "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' "
1521 " FROM pg_attrdef;\n",
1522 "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' "
1523 " FROM pg_language;\n",
1524 "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' "
1525 " FROM pg_operator;\n",
1526 "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' "
1527 " FROM pg_opclass;\n",
1528 "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' "
1529 " FROM pg_rewrite;\n",
1530 "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' "
1531 " FROM pg_trigger;\n",
1534 * restriction here to avoid pinning the public namespace
1536 "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' "
1537 " FROM pg_namespace "
1538 " WHERE nspname LIKE 'pg%';\n",
1542 fputs(_("initializing pg_depend ... "), stdout);
1545 snprintf(cmd, sizeof(cmd),
1546 "\"%s\" %s template1 >%s",
1547 backend_exec, backend_options,
1552 for (line = pg_depend_setup; *line != NULL; line++)
1561 * set up system views
1564 setup_sysviews(void)
1568 char **sysviews_setup;
1570 fputs(_("creating system views ... "), stdout);
1573 sysviews_setup = readfile(system_views_file);
1576 * We use -N here to avoid backslashing stuff in system_views.sql
1578 snprintf(cmd, sizeof(cmd),
1579 "\"%s\" %s -N template1 >%s",
1580 backend_exec, backend_options,
1585 for (line = sysviews_setup; *line != NULL; line++)
1593 free(sysviews_setup);
1599 * load description data
1602 setup_description(void)
1606 fputs(_("loading pg_description ... "), stdout);
1609 snprintf(cmd, sizeof(cmd),
1610 "\"%s\" %s template1 >%s",
1611 backend_exec, backend_options,
1616 PG_CMD_PUTS("CREATE TEMP TABLE tmp_pg_description ( "
1620 " description text) WITHOUT OIDS;\n");
1622 PG_CMD_PRINTF1("COPY tmp_pg_description FROM '%s';\n",
1625 PG_CMD_PUTS("INSERT INTO pg_description "
1626 " SELECT t.objoid, c.oid, t.objsubid, t.description "
1627 " FROM tmp_pg_description t, pg_class c "
1628 " WHERE c.relname = t.classname;\n");
1636 * load conversion functions
1639 setup_conversion(void)
1645 fputs(_("creating conversions ... "), stdout);
1648 snprintf(cmd, sizeof(cmd),
1649 "\"%s\" %s template1 >%s",
1650 backend_exec, backend_options,
1655 conv_lines = readfile(conversion_file);
1656 for (line = conv_lines; *line != NULL; line++)
1658 if (strstr(*line, "DROP CONVERSION") != *line)
1673 * We set most system catalogs and built-in functions as world-accessible.
1674 * Some objects may require different permissions by default, so we
1675 * make sure we don't overwrite privilege sets that have already been
1679 setup_privileges(void)
1684 static char *privileges_setup[] = {
1686 " SET relacl = '{\"=r/\\\\\"$POSTGRES_SUPERUSERNAME\\\\\"\"}' "
1687 " WHERE relkind IN ('r', 'v', 'S') AND relacl IS NULL;\n",
1689 " SET proacl = '{\"=X/\\\\\"$POSTGRES_SUPERUSERNAME\\\\\"\"}' "
1690 " WHERE proacl IS NULL;\n",
1691 "UPDATE pg_language "
1692 " SET lanacl = '{\"=U/\\\\\"$POSTGRES_SUPERUSERNAME\\\\\"\"}' "
1693 " WHERE lanpltrusted;\n",
1694 "GRANT USAGE ON SCHEMA pg_catalog TO PUBLIC;\n",
1695 "GRANT CREATE, USAGE ON SCHEMA public TO PUBLIC;\n",
1699 fputs(_("setting privileges on built-in objects ... "), stdout);
1702 snprintf(cmd, sizeof(cmd),
1703 "\"%s\" %s template1 >%s",
1704 backend_exec, backend_options,
1709 priv_lines = replace_token(privileges_setup,
1710 "$POSTGRES_SUPERUSERNAME", effective_user);
1711 for (line = priv_lines; *line != NULL; line++)
1720 * extract the strange version of version required for information schema
1724 set_info_version(void)
1726 char *letterversion;
1731 char *vstr = xstrdup(PG_VERSION);
1734 ptr = vstr + (strlen(vstr) - 1);
1735 while (ptr != vstr && (*ptr < '0' || *ptr > '9'))
1737 letterversion = ptr + 1;
1738 major = strtol(vstr, &endptr, 10);
1740 minor = strtol(endptr + 1, &endptr, 10);
1742 micro = strtol(endptr + 1, &endptr, 10);
1743 snprintf(infoversion, sizeof(infoversion), "%02ld.%02ld.%04ld%s",
1744 major, minor, micro, letterversion);
1748 * load info schema and populate from features file
1757 fputs(_("creating information schema ... "), stdout);
1760 lines = readfile(info_schema_file);
1763 * We use -N here to avoid backslashing stuff in
1764 * information_schema.sql
1766 snprintf(cmd, sizeof(cmd),
1767 "\"%s\" %s -N template1 >%s",
1768 backend_exec, backend_options,
1773 for (line = lines; *line != NULL; line++)
1783 snprintf(cmd, sizeof(cmd),
1784 "\"%s\" %s template1 >%s",
1785 backend_exec, backend_options,
1790 PG_CMD_PRINTF1("UPDATE information_schema.sql_implementation_info "
1791 " SET character_value = '%s' "
1792 " WHERE implementation_info_name = 'DBMS VERSION';\n",
1795 PG_CMD_PRINTF1("COPY information_schema.sql_features "
1796 " (feature_id, feature_name, sub_feature_id, "
1797 " sub_feature_name, is_supported, comments) "
1807 * clean everything up in template1
1814 fputs(_("vacuuming database template1 ... "), stdout);
1817 snprintf(cmd, sizeof(cmd),
1818 "\"%s\" %s template1 >%s",
1819 backend_exec, backend_options,
1824 PG_CMD_PUTS("ANALYZE;\nVACUUM FULL;\nVACUUM FREEZE;\n");
1832 * copy template1 to template0
1835 make_template0(void)
1839 static char *template0_setup[] = {
1840 "CREATE DATABASE template0;\n",
1841 "UPDATE pg_database SET "
1842 " datistemplate = 't', "
1843 " datallowconn = 'f' "
1844 " WHERE datname = 'template0';\n",
1847 * We use the OID of template0 to determine lastsysoid
1849 "UPDATE pg_database SET datlastsysoid = "
1850 " (SELECT oid::int4 - 1 FROM pg_database "
1851 " WHERE datname = 'template0');\n",
1854 * Explicitly revoke public create-schema and create-temp-table
1855 * privileges in template1 and template0; else the latter would be
1858 "REVOKE CREATE,TEMPORARY ON DATABASE template1 FROM public;\n",
1859 "REVOKE CREATE,TEMPORARY ON DATABASE template0 FROM public;\n",
1862 * Finally vacuum to clean up dead rows in pg_database
1864 "VACUUM FULL pg_database;\n",
1868 fputs(_("copying template1 to template0 ... "), stdout);
1871 snprintf(cmd, sizeof(cmd),
1872 "\"%s\" %s template1 >%s",
1873 backend_exec, backend_options,
1878 for (line = template0_setup; *line; line++)
1888 * signal handler in case we are interrupted.
1890 * The Windows runtime docs at
1891 * http://msdn.microsoft.com/library/en-us/vclib/html/_crt_signal.asp
1892 * specifically forbid a number of things being done from a signal handler,
1893 * including IO, memory allocation and system calls, and only allow jmpbuf
1894 * if you are handling SIGFPE.
1896 * I avoided doing the forbidden things by setting a flag instead of calling
1897 * exit_nicely() directly.
1899 * Also note the behaviour of Windows with SIGINT, which says this:
1900 * Note SIGINT is not supported for any Win32 application, including
1901 * Windows 98/Me and Windows NT/2000/XP. When a CTRL+C interrupt occurs,
1902 * Win32 operating systems generate a new thread to specifically handle
1903 * that interrupt. This can cause a single-thread application such as UNIX,
1904 * to become multithreaded, resulting in unexpected behavior.
1906 * I have no idea how to handle this. (Strange they call UNIX an application!)
1907 * So this will need some testing on Windows.
1912 /* handle systems that reset the handler, like Windows (grr) */
1913 pqsignal(signum, trapsig);
1914 caught_signal = true;
1918 * call exit_nicely() if we got a signal, or else output "ok".
1925 printf(_("caught signal\n"));
1929 else if (output_failed)
1931 printf(_("could not write to child process: %s\n"),
1932 strerror(output_errno));
1938 /* all seems well */
1945 * Escape any single quotes or backslashes in given string
1948 escape_quotes(const char *src)
1950 int len = strlen(src),
1952 char *result = xmalloc(len * 2 + 1);
1954 for (i = 0, j = 0; i < len; i++)
1956 if (src[i] == '\'' || src[i] == '\\')
1958 result[j++] = src[i];
1965 * check if given string is a valid locale specifier
1968 chklocale(const char *locale)
1971 int category = LC_CTYPE;
1974 save = setlocale(category, NULL);
1976 return false; /* should not happen; */
1978 save = xstrdup(save);
1980 ret = (setlocale(category, locale) != NULL);
1982 setlocale(category, save);
1985 /* should we exit here? */
1987 fprintf(stderr, _("%s: invalid locale name \"%s\"\n"), progname, locale);
1993 * set up the locale variables
1995 * assumes we have called setlocale(LC_ALL,"")
2000 /* set empty lc_* values to locale config if set */
2002 if (strlen(locale) > 0)
2004 if (strlen(lc_ctype) == 0)
2006 if (strlen(lc_collate) == 0)
2007 lc_collate = locale;
2008 if (strlen(lc_numeric) == 0)
2009 lc_numeric = locale;
2010 if (strlen(lc_time) == 0)
2012 if (strlen(lc_monetary) == 0)
2013 lc_monetary = locale;
2014 if (strlen(lc_messages) == 0)
2015 lc_messages = locale;
2019 * override absent/invalid config settings from initdb's locale
2023 if (strlen(lc_ctype) == 0 || !chklocale(lc_ctype))
2024 lc_ctype = xstrdup(setlocale(LC_CTYPE, NULL));
2025 if (strlen(lc_collate) == 0 || !chklocale(lc_collate))
2026 lc_collate = xstrdup(setlocale(LC_COLLATE, NULL));
2027 if (strlen(lc_numeric) == 0 || !chklocale(lc_numeric))
2028 lc_numeric = xstrdup(setlocale(LC_NUMERIC, NULL));
2029 if (strlen(lc_time) == 0 || !chklocale(lc_time))
2030 lc_time = xstrdup(setlocale(LC_TIME, NULL));
2031 if (strlen(lc_monetary) == 0 || !chklocale(lc_monetary))
2032 lc_monetary = xstrdup(setlocale(LC_MONETARY, NULL));
2033 if (strlen(lc_messages) == 0 || !chklocale(lc_messages))
2034 #if defined(LC_MESSAGES) && !defined(WIN32)
2036 /* when available get the current locale setting */
2037 lc_messages = xstrdup(setlocale(LC_MESSAGES, NULL));
2041 /* when not available, get the CTYPE setting */
2042 lc_messages = xstrdup(setlocale(LC_CTYPE, NULL));
2052 usage(const char *progname)
2054 printf(_("%s initializes a PostgreSQL database cluster.\n\n"), progname);
2055 printf(_("Usage:\n"));
2056 printf(_(" %s [OPTION]... [DATADIR]\n"), progname);
2057 printf(_("\nOptions:\n"));
2058 printf(_(" [-D, --pgdata=]DATADIR location for this database cluster\n"));
2059 printf(_(" -E, --encoding=ENCODING set default encoding for new databases\n"));
2060 printf(_(" --locale=LOCALE initialize database cluster with given locale\n"));
2061 printf(_(" --lc-collate, --lc-ctype, --lc-messages=LOCALE\n"
2062 " --lc-monetary, --lc-numeric, --lc-time=LOCALE\n"
2063 " initialize database cluster with given locale\n"
2064 " in the respective category (default taken from\n"
2065 " environment)\n"));
2066 printf(_(" --no-locale equivalent to --locale=C\n"));
2067 printf(_(" -A, --auth=METHOD default authentication method for local connections\n"));
2068 printf(_(" -U, --username=NAME database superuser name\n"));
2069 printf(_(" -W, --pwprompt prompt for a password for the new superuser\n"));
2070 printf(_(" --pwfile=FILE read password for the new superuser from file\n"));
2071 printf(_(" -?, --help show this help, then exit\n"));
2072 printf(_(" -V, --version output version information, then exit\n"));
2073 printf(_("\nLess commonly used options:\n"));
2074 printf(_(" -d, --debug generate lots of debugging output\n"));
2075 printf(_(" -s, --show show internal settings\n"));
2076 printf(_(" -L DIRECTORY where to find the input files\n"));
2077 printf(_(" -n, --noclean do not clean up after errors\n"));
2078 printf(_("\nIf the data directory is not specified, the environment variable PGDATA\n"
2080 printf(_("\nReport bugs to <pgsql-bugs@postgresql.org>.\n"));
2084 main(int argc, char *argv[])
2087 * options with no short version return a low integer, the rest return
2088 * their short version value
2090 static struct option long_options[] = {
2091 {"pgdata", required_argument, NULL, 'D'},
2092 {"encoding", required_argument, NULL, 'E'},
2093 {"locale", required_argument, NULL, 1},
2094 {"lc-collate", required_argument, NULL, 2},
2095 {"lc-ctype", required_argument, NULL, 3},
2096 {"lc-monetary", required_argument, NULL, 4},
2097 {"lc-numeric", required_argument, NULL, 5},
2098 {"lc-time", required_argument, NULL, 6},
2099 {"lc-messages", required_argument, NULL, 7},
2100 {"no-locale", no_argument, NULL, 8},
2101 {"auth", required_argument, NULL, 'A'},
2102 {"pwprompt", no_argument, NULL, 'W'},
2103 {"pwfile", required_argument, NULL, 9},
2104 {"username", required_argument, NULL, 'U'},
2105 {"help", no_argument, NULL, '?'},
2106 {"version", no_argument, NULL, 'V'},
2107 {"debug", no_argument, NULL, 'd'},
2108 {"show", no_argument, NULL, 's'},
2109 {"noclean", no_argument, NULL, 'n'},
2117 char *short_version;
2118 char *pgdenv; /* PGDATA value gotten from and sent to
2120 char bin_dir[MAXPGPATH];
2121 char *pg_data_native;
2122 static const char *subdirs[] = {
2125 "pg_xlog/archive_status",
2133 progname = get_progname(argv[0]);
2134 set_pglocale_pgservice(argv[0], "initdb");
2138 if (strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-?") == 0)
2143 if (strcmp(argv[1], "--version") == 0 || strcmp(argv[1], "-V") == 0)
2145 puts("initdb (PostgreSQL) " PG_VERSION);
2150 /* process command-line options */
2152 while ((c = getopt_long(argc, argv, "dD:E:L:nU:WA:s", long_options, &option_index)) != -1)
2157 authmethod = xstrdup(optarg);
2160 pg_data = xstrdup(optarg);
2163 encoding = xstrdup(optarg);
2169 username = xstrdup(optarg);
2173 printf(_("Running in debug mode.\n"));
2177 printf(_("Running in noclean mode. Mistakes will not be cleaned up.\n"));
2180 share_path = xstrdup(optarg);
2183 locale = xstrdup(optarg);
2186 lc_collate = xstrdup(optarg);
2189 lc_ctype = xstrdup(optarg);
2192 lc_monetary = xstrdup(optarg);
2195 lc_numeric = xstrdup(optarg);
2198 lc_time = xstrdup(optarg);
2201 lc_messages = xstrdup(optarg);
2207 pwfilename = xstrdup(optarg);
2210 show_setting = true;
2213 /* getopt_long already emitted a complaint */
2214 fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
2220 /* Non-option argument specifies data directory */
2223 pg_data = xstrdup(argv[optind]);
2229 fprintf(stderr, _("%s: too many command-line arguments (first is \"%s\")\n"),
2230 progname, argv[optind + 1]);
2231 fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
2235 if (pwprompt && pwfilename)
2237 fprintf(stderr, _("%s: password prompt and password file may not be specified together\n"), progname);
2241 if (authmethod == NULL || !strlen(authmethod))
2243 authwarning = _("\nWARNING: enabling \"trust\" authentication for local connections\n"
2244 "You can change this by editing pg_hba.conf or using the -A option the\n"
2245 "next time you run initdb.\n");
2246 authmethod = "trust";
2249 if (strcmp(authmethod, "md5") &&
2250 strcmp(authmethod, "ident") &&
2251 strncmp(authmethod, "ident ", 6) && /* ident with space =
2253 strcmp(authmethod, "trust") &&
2255 strcmp(authmethod, "pam") &&
2256 strncmp(authmethod, "pam ", 4) && /* pam with space = param */
2258 strcmp(authmethod, "crypt") &&
2259 strcmp(authmethod, "password")
2263 * Kerberos methods not listed because they are not supported over
2264 * local connections and are rejected in hba.c
2267 fprintf(stderr, _("%s: unrecognized authentication method \"%s\"\n"),
2268 progname, authmethod);
2272 if ((!strcmp(authmethod, "md5") ||
2273 !strcmp(authmethod, "crypt") ||
2274 !strcmp(authmethod, "password")) &&
2275 !(pwprompt || pwfilename))
2277 fprintf(stderr, _("%s: must specify a password for the superuser to enable %s authentication\n"), progname, authmethod);
2281 if (strlen(pg_data) == 0)
2283 pgdenv = getenv("PGDATA");
2284 if (pgdenv && strlen(pgdenv))
2287 pg_data = xstrdup(pgdenv);
2292 _("%s: no data directory specified\n"
2293 "You must identify the directory where the data for this database system\n"
2294 "will reside. Do this with either the invocation option -D or the\n"
2295 "environment variable PGDATA.\n"),
2301 pg_data_native = pg_data;
2302 canonicalize_path(pg_data);
2305 * we have to set PGDATA for postgres rather than pass it on the
2306 * command line to avoid dumb quoting problems on Windows, and we
2307 * would especially need quotes otherwise on Windows because paths
2308 * there are most likely to have embedded spaces.
2310 pgdenv = xmalloc(8 + strlen(pg_data));
2311 sprintf(pgdenv, "PGDATA=%s", pg_data);
2314 if ((ret = find_other_exec(argv[0], "postgres", PG_VERSIONSTR,
2317 char full_path[MAXPGPATH];
2319 if (find_my_exec(argv[0], full_path) < 0)
2320 StrNCpy(full_path, progname, MAXPGPATH);
2324 _("The program \"postgres\" is needed by %s "
2325 "but was not found in the\n"
2326 "same directory as \"%s\".\n"
2327 "Check your installation.\n"),
2328 progname, full_path);
2331 _("The program \"postgres\" was found by \"%s\"\n"
2332 "but was not the same version as %s.\n"
2333 "Check your installation.\n"),
2334 full_path, progname);
2338 /* store binary directory */
2339 strcpy(bin_path, backend_exec);
2340 *last_dir_separator(bin_path) = '\0';
2341 canonicalize_path(bin_path);
2345 share_path = xmalloc(MAXPGPATH);
2346 get_share_path(backend_exec, share_path);
2348 else if (!is_absolute_path(share_path))
2350 fprintf(stderr, _("%s: input file location must be an absolute path\n"), progname);
2354 canonicalize_path(share_path);
2356 if ((short_version = get_short_version()) == NULL)
2358 fprintf(stderr, _("%s: could not determine valid short version string\n"), progname);
2362 if (strlen(username))
2363 effective_user = username;
2365 effective_user = get_id();
2367 if (strlen(encoding))
2368 encodingid = get_encoding_id(encoding);
2370 set_input(&bki_file, "postgres.bki");
2371 set_input(&desc_file, "postgres.description");
2372 set_input(&hba_file, "pg_hba.conf.sample");
2373 set_input(&ident_file, "pg_ident.conf.sample");
2374 set_input(&conf_file, "postgresql.conf.sample");
2375 set_input(&conversion_file, "conversion_create.sql");
2376 set_input(&info_schema_file, "information_schema.sql");
2377 set_input(&features_file, "sql_features.txt");
2378 set_input(&system_views_file, "system_views.sql");
2382 if (show_setting || debug)
2386 "PGDATA=%s\nshare_path=%s\nPGPATH=%s\n"
2387 "POSTGRES_SUPERUSERNAME=%s\nPOSTGRES_BKI=%s\n"
2388 "POSTGRES_DESCR=%s\nPOSTGRESQL_CONF_SAMPLE=%s\n"
2389 "PG_HBA_SAMPLE=%s\nPG_IDENT_SAMPLE=%s\n",
2391 pg_data, share_path, bin_path,
2392 effective_user, bki_file,
2393 desc_file, conf_file,
2394 hba_file, ident_file);
2399 check_input(bki_file);
2400 check_input(desc_file);
2401 check_input(hba_file);
2402 check_input(ident_file);
2403 check_input(conf_file);
2404 check_input(conversion_file);
2405 check_input(info_schema_file);
2406 check_input(features_file);
2407 check_input(system_views_file);
2411 printf(_("The files belonging to this database system will be owned "
2413 "This user must also own the server process.\n\n"),
2416 if (strcmp(lc_ctype, lc_collate) == 0 &&
2417 strcmp(lc_ctype, lc_time) == 0 &&
2418 strcmp(lc_ctype, lc_numeric) == 0 &&
2419 strcmp(lc_ctype, lc_monetary) == 0 &&
2420 strcmp(lc_ctype, lc_messages) == 0)
2421 printf(_("The database cluster will be initialized with locale %s.\n"), lc_ctype);
2424 printf(_("The database cluster will be initialized with locales\n"
2439 #if defined(HAVE_LANGINFO_H) && defined(CODESET)
2440 if (strcmp(lc_ctype, "C") != 0 && strcmp(lc_ctype, "POSIX") != 0)
2442 if (strlen(encoding) == 0)
2446 tmp = find_matching_encoding(lc_ctype);
2449 fprintf(stderr, _("%s: could not find suitable encoding for locale \"%s\"\n"), progname, lc_ctype);
2450 fprintf(stderr, _("Rerun %s with the -E option.\n"), progname);
2451 fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
2456 encodingid = encodingid_to_string(tmp);
2457 printf(_("The default database encoding has accordingly been set to %s.\n"),
2458 pg_encoding_to_char(tmp));
2462 check_encodings_match(atoi(encodingid), lc_ctype);
2464 #endif /* HAVE_LANGINFO_H && CODESET */
2471 * now we are starting to do real work, trap signals so we can clean
2475 /* some of these are not valid on Windows */
2477 pqsignal(SIGHUP, trapsig);
2480 pqsignal(SIGINT, trapsig);
2483 pqsignal(SIGQUIT, trapsig);
2486 pqsignal(SIGTERM, trapsig);
2489 /* Ignore SIGPIPE when writing to backend, so we can clean up */
2491 pqsignal(SIGPIPE, SIG_IGN);
2494 switch (check_data_dir())
2497 /* PGDATA not there, must create it */
2498 printf(_("creating directory %s ... "),
2502 if (!mkdatadir(NULL))
2507 made_new_pgdata = true;
2511 /* Present but empty, fix permissions and use it */
2512 printf(_("fixing permissions on existing directory %s ... "),
2516 if (chmod(pg_data, 0700) != 0)
2518 fprintf(stderr, _("%s: could not change permissions of directory \"%s\": %s\n"),
2519 progname, pg_data, strerror(errno));
2525 found_existing_pgdata = true;
2529 /* Present and not empty */
2531 _("%s: directory \"%s\" exists but is not empty\n"
2532 "If you want to create a new database system, either remove or empty\n"
2533 "the directory \"%s\" or run %s\n"
2534 "with an argument other than \"%s\".\n"),
2535 progname, pg_data, pg_data, progname, pg_data);
2536 exit(1); /* no further message needed */
2539 /* Trouble accessing directory */
2540 fprintf(stderr, _("%s: could not access directory \"%s\": %s\n"),
2541 progname, pg_data, strerror(errno));
2545 /* Create required subdirectories */
2547 for (i = 0; i < (sizeof(subdirs) / sizeof(char *)); i++)
2549 printf(_("creating directory %s/%s ... "), pg_data, subdirs[i]);
2552 if (!mkdatadir(subdirs[i]))
2558 /* Top level PG_VERSION is checked by bootstrapper, so make it first */
2559 set_short_version(short_version, NULL);
2562 * Determine platform-specific config settings
2564 * Use reasonable values if kernel will let us, else scale back. Probe
2565 * for max_connections first since it is subject to more constraints
2566 * than shared_buffers.
2574 /* Now create all the text config files */
2577 /* Bootstrap template1 */
2578 bootstrap_template1(short_version);
2581 * Make the per-database PG_VERSION for template1 only after init'ing
2584 set_short_version(short_version, "base/1");
2586 /* Create the stuff we don't need to use bootstrap mode for */
2589 if (pwprompt || pwfilename)
2592 unlimit_systables();
2598 setup_description();
2610 if (authwarning != NULL)
2611 fprintf(stderr, authwarning);
2613 /* Get directory specification used to start this executable */
2614 strcpy(bin_dir, argv[0]);
2615 get_parent_directory(bin_dir);
2617 printf(_("\nSuccess. You can now start the database server using:\n\n"
2618 " %s%s%s%spostmaster -D %s%s%s\n"
2620 " %s%s%s%spg_ctl -D %s%s%s -l logfile start\n\n"),
2621 QUOTE_PATH, bin_dir, QUOTE_PATH, (strlen(bin_dir) > 0) ? DIR_SEP : "",
2622 QUOTE_PATH, pg_data_native, QUOTE_PATH,
2623 QUOTE_PATH, bin_dir, QUOTE_PATH, (strlen(bin_dir) > 0) ? DIR_SEP : "",
2624 QUOTE_PATH, pg_data_native, QUOTE_PATH);