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-2003, 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.48 2004/08/11 11:06:23 petere Exp $
44 *-------------------------------------------------------------------------
47 #include "postgres_fe.h"
55 #ifdef HAVE_LANGINFO_H
56 # include <langinfo.h>
59 #include "libpq/pqsignal.h"
60 #include "mb/pg_wchar.h"
61 #include "getopt_long.h"
68 #define _(x) gettext((x))
70 /* version string we expect back from postgres */
71 #define PG_VERSIONSTR "postgres (PostgreSQL) " PG_VERSION "\n"
74 * these values are passed in by makefile defines
76 char *share_path = NULL;
78 /* values to be obtained from arguments */
82 char *lc_collate = "";
84 char *lc_monetary = "";
85 char *lc_numeric = "";
87 char *lc_messages = "";
89 bool pwprompt = false;
90 char *pwfilename = NULL;
91 char *authmethod = "";
94 bool show_setting = false;
100 char *encodingid = "0";
106 char *conversion_file;
107 char *info_schema_file;
109 char *system_views_file;
110 char *effective_user;
111 bool testpath = true;
112 bool made_new_pgdata = false;
113 bool found_existing_pgdata = false;
114 char infoversion[100];
115 bool caught_signal = false;
116 bool output_failed = false;
119 int n_connections = 10;
123 * Warning messages for authentication methods
125 char *authtrust_warning = \
126 "# CAUTION: Configuring the system for local \"trust\" authentication allows\n"
127 "# any local user to connect as any PostgreSQL user, including the database\n"
128 "# superuser. If you do not trust all your local users, use another\n"
129 "# authenication method.\n";
130 char *authwarning = NULL;
133 * Centralized knowledge of switches to pass to backend
135 * Note: in the shell-script version, we also passed PGDATA as a -D switch,
136 * but here it is more convenient to pass it as an environment variable
137 * (no quoting to worry about).
139 static const char *boot_options = "-F";
140 static const char *backend_options = "-F -O -c search_path=pg_catalog -c exit_on_error=true";
143 /* path to 'initdb' binary directory */
144 char bin_path[MAXPGPATH];
145 char backend_exec[MAXPGPATH];
147 static void *xmalloc(size_t size);
148 static char *xstrdup(const char *s);
149 static char **replace_token(char **lines, char *token, char *replacement);
150 static char **readfile(char *path);
151 static void writefile(char *path, char **lines);
152 static int mkdir_p(char *path, mode_t omode);
153 static void exit_nicely(void);
154 static char *get_id(void);
155 static char *get_encoding_id(char *encoding_name);
156 static char *get_short_version(void);
157 static int check_data_dir(void);
158 static bool mkdatadir(const char *subdir);
159 static void set_input(char **dest, char *filename);
160 static void check_input(char *path);
161 static void set_short_version(char *short_version, char *extrapath);
162 static void set_null_conf(void);
163 static void test_connections(void);
164 static void test_buffers(void);
165 static void setup_config(void);
166 static void bootstrap_template1(char *short_version);
167 static void setup_shadow(void);
168 static void get_set_pwd(void);
169 static void unlimit_systables(void);
170 static void setup_depend(void);
171 static void setup_sysviews(void);
172 static void setup_description(void);
173 static void setup_conversion(void);
174 static void setup_privileges(void);
175 static void set_info_version(void);
176 static void setup_schema(void);
177 static void vacuum_db(void);
178 static void make_template0(void);
179 static void trapsig(int signum);
180 static void check_ok(void);
181 static bool chklocale(const char *locale);
182 static void setlocales(void);
183 static void usage(const char *progname);
187 * macros for running pipes to postgres
189 #define PG_CMD_DECL char cmd[MAXPGPATH]; char ** line ; FILE * pg
190 #define PG_CMD_DECL_NOLINE char cmd[MAXPGPATH]; FILE * pg
192 #define PG_CMD_OPEN \
196 pg = popen(cmd, "w"); \
201 #define PG_CMD_CLOSE \
203 if (pclose_check(pg)) \
207 #define PG_CMD_PUTLINE \
209 if (fputs(*line, pg) < 0 || fflush(pg) < 0) \
210 output_failed = true; \
214 #define QUOTE_PATH ""
216 #define QUOTE_PATH "\""
220 * routines to check mem allocations and fail noisily.
222 * Note that we can't call exit_nicely() on a memory failure, as it calls
223 * rmtree() which needs memory allocation. So we just exit with a bang.
230 result = malloc(size);
233 fprintf(stderr, _("%s: out of memory\n"), progname);
240 xstrdup(const char *s)
247 fprintf(stderr, _("%s: out of memory\n"), progname);
254 * make a copy of the array of lines, with token replaced by replacement
255 * the first time it occurs on each line.
257 * This does most of what sed was used for in the shell script, but
258 * doesn't need any regexp stuff.
261 replace_token(char **lines, char *token, char *replacement)
270 for (i = 0; lines[i]; i++)
273 result = (char **) xmalloc(numlines * sizeof(char *));
275 toklen = strlen(token);
276 replen = strlen(replacement);
277 diff = replen - toklen;
279 for (i = 0; i < numlines; i++)
285 /* just copy pointer if NULL or no change needed */
287 if (lines[i] == NULL || (where = strstr(lines[i], token)) == NULL)
289 result[i] = lines[i];
293 /* if we get here a change is needed - set up new line */
295 newline = (char *) xmalloc(strlen(lines[i]) + diff + 1);
297 pre = where - lines[i];
299 strncpy(newline, lines[i], pre);
301 strcpy(newline + pre, replacement);
303 strcpy(newline + pre + replen, lines[i] + pre + toklen);
314 * get the lines from a text file
327 if ((infile = fopen(path, "r")) == NULL)
329 fprintf(stderr, _("%s: could not open file \"%s\" for reading: %s\n"),
330 progname, path, strerror(errno));
334 /* pass over the file twice - the first time to size the result */
336 while ((c = fgetc(infile)) != EOF)
342 if (linelen > maxlength)
348 /* handle last line without a terminating newline (yuck) */
352 if (linelen > maxlength)
355 /* set up the result and the line buffer */
357 result = (char **) xmalloc((nlines + 2) * sizeof(char *));
358 buffer = (char *) xmalloc(maxlength + 2);
360 /* now reprocess the file and store the lines */
364 while (fgets(buffer, maxlength + 1, infile) != NULL)
366 result[nlines] = xstrdup(buffer);
371 result[nlines] = NULL;
377 * write an array of lines to a file
380 writefile(char *path, char **lines)
385 if ((out_file = fopen(path, PG_BINARY_W)) == NULL)
387 fprintf(stderr, _("%s: could not open file \"%s\" for writing: %s\n"),
388 progname, path, strerror(errno));
391 for (line = lines; *line != NULL; line++)
393 if (fputs(*line, out_file) < 0)
397 if (fclose(out_file))
401 /* source stolen from FreeBSD /src/bin/mkdir/mkdir.c and adapted */
404 * this tries to build all the elements of a path to a directory a la mkdir -p
405 * we assume the path is in canonical form, i.e. uses / as the separator
406 * we also assume it isn't null.
409 mkdir_p(char *path, mode_t omode)
424 /* skip network and drive specifiers for win32 */
427 if (p[0] == '/' && p[1] == '/')
430 p = strstr(p + 2, "/");
434 else if (p[1] == ':' &&
435 ((p[0] >= 'a' && p[0] <= 'z') ||
436 (p[0] >= 'A' && p[0] <= 'Z')))
444 if (p[0] == '/') /* Skip leading '/'. */
446 for (first = 1, last = 0; !last; ++p)
450 else if (p[0] != '/')
453 if (!last && p[1] == '\0')
458 * POSIX 1003.2: For each dir operand that does not name an
459 * existing directory, effects equivalent to those cased by
460 * the following command shall occcur:
462 * mkdir -p -m $(umask -S),u+wx $(dirname dir) && mkdir [-m mode]
465 * We change the user's umask and then restore it, instead of
469 numask = oumask & ~(S_IWUSR | S_IXUSR);
470 (void) umask(numask);
474 (void) umask(oumask);
475 if (mkdir(path, last ? omode : S_IRWXU | S_IRWXG | S_IRWXO) < 0)
477 if (errno == EEXIST || errno == EISDIR)
479 if (stat(path, &sb) < 0)
484 else if (!S_ISDIR(sb.st_mode))
504 (void) umask(oumask);
509 * clean up any files we created on failure
510 * if we created the data directory remove it too
515 fprintf(stderr, _("%s: failed\n"), progname);
521 fprintf(stderr, _("%s: removing data directory \"%s\"\n"),
523 if (!rmtree(pg_data, true))
524 fprintf(stderr, _("%s: failed\n"), progname);
526 else if (found_existing_pgdata)
529 _("%s: removing contents of data directory \"%s\"\n"),
531 if (!rmtree(pg_data, false))
532 fprintf(stderr, _("%s: failed\n"), progname);
534 /* otherwise died during startup, do nothing! */
538 if (made_new_pgdata || found_existing_pgdata)
540 _("%s: data directory \"%s\" not removed at user's request\n"),
548 * find the current user
550 * on unix make sure it isn't really root
559 pw = getpwuid(getuid());
561 #ifndef __BEOS__ /* no root check on BEOS */
563 if (!geteuid()) /* 0 is root's uid */
566 _("%s: cannot be run as root\n"
567 "Please log in (using, e.g., \"su\") as the "
568 "(unprivileged) user that will\n"
569 "own the server process.\n"),
575 #else /* the windows code */
582 struct passwd_win32 *pw = &pass_win32;
583 DWORD pwname_size = sizeof(pass_win32.pw_name) - 1;
586 GetUserName(pw->pw_name, &pwname_size);
589 return xstrdup(pw->pw_name);
593 encodingid_to_string(int enc)
597 sprintf(result, "%d", enc);
598 return xstrdup(result);
602 * get the encoding id for a given encoding name
605 get_encoding_id(char *encoding_name)
609 if (encoding_name && *encoding_name)
611 if ((enc = pg_char_to_encoding(encoding_name)) >= 0 &&
612 pg_valid_server_encoding(encoding_name) >= 0)
614 return encodingid_to_string(enc);
617 fprintf(stderr, _("%s: \"%s\" is not a valid server encoding name\n"),
618 progname, encoding_name ? encoding_name : "(null)");
622 #if defined(HAVE_LANGINFO_H) && defined(CODESET)
624 * Checks whether the encoding selected for PostgreSQL and the
625 * encoding used by the system locale match.
628 struct encoding_match
630 enum pg_enc pg_enc_code;
631 char *system_enc_name;
634 struct encoding_match encoding_match_list[] = {
635 { PG_EUC_JP, "EUC-JP" },
636 { PG_EUC_JP, "eucJP" },
637 { PG_EUC_JP, "IBM-eucJP" },
638 { PG_EUC_JP, "sdeckanji" },
640 { PG_EUC_CN, "EUC-CN" },
641 { PG_EUC_CN, "eucCN" },
642 { PG_EUC_CN, "IBM-eucCN" },
643 { PG_EUC_CN, "GB2312" },
644 { PG_EUC_CN, "dechanzi" },
646 { PG_EUC_KR, "EUC-KR" },
647 { PG_EUC_KR, "eucKR" },
648 { PG_EUC_KR, "IBM-eucKR" },
649 { PG_EUC_KR, "deckorean" },
650 { PG_EUC_KR, "5601" },
652 { PG_EUC_TW, "EUC-TW" },
653 { PG_EUC_TW, "eucTW" },
654 { PG_EUC_TW, "IBM-eucTW" },
655 { PG_EUC_TW, "cns11643" },
661 { PG_UTF8, "UTF-8" },
664 { PG_LATIN1, "ISO-8859-1" },
665 { PG_LATIN1, "ISO8859-1" },
666 { PG_LATIN1, "iso88591" },
668 { PG_LATIN2, "ISO-8859-2" },
669 { PG_LATIN2, "ISO8859-2" },
670 { PG_LATIN2, "iso88592" },
672 { PG_LATIN3, "ISO-8859-3" },
673 { PG_LATIN3, "ISO8859-3" },
674 { PG_LATIN3, "iso88593" },
676 { PG_LATIN4, "ISO-8859-4" },
677 { PG_LATIN4, "ISO8859-4" },
678 { PG_LATIN4, "iso88594" },
680 { PG_LATIN5, "ISO-8859-9" },
681 { PG_LATIN5, "ISO8859-9" },
682 { PG_LATIN5, "iso88599" },
684 { PG_LATIN6, "ISO-8859-10" },
685 { PG_LATIN6, "ISO8859-10" },
686 { PG_LATIN6, "iso885910" },
688 { PG_LATIN7, "ISO-8859-13" },
689 { PG_LATIN7, "ISO8859-13" },
690 { PG_LATIN7, "iso885913" },
692 { PG_LATIN8, "ISO-8859-14" },
693 { PG_LATIN8, "ISO8859-14" },
694 { PG_LATIN8, "iso885914" },
696 { PG_LATIN9, "ISO-8859-15" },
697 { PG_LATIN9, "ISO8859-15" },
698 { PG_LATIN9, "iso885915" },
700 { PG_LATIN10, "ISO-8859-16" },
701 { PG_LATIN10, "ISO8859-16" },
702 { PG_LATIN10, "iso885916" },
704 { PG_WIN1256, "CP1256" },
705 { PG_TCVN, "CP1258" },
707 { PG_WIN874, "???" },
709 { PG_KOI8R, "KOI8-R" },
710 { PG_WIN1251, "CP1251" },
713 { PG_ISO_8859_5, "ISO-8859-5" },
714 { PG_ISO_8859_5, "ISO8859-5" },
715 { PG_ISO_8859_5, "iso88595" },
717 { PG_ISO_8859_6, "ISO-8859-6" },
718 { PG_ISO_8859_6, "ISO8859-6" },
719 { PG_ISO_8859_6, "iso88596" },
721 { PG_ISO_8859_7, "ISO-8859-7" },
722 { PG_ISO_8859_7, "ISO8859-7" },
723 { PG_ISO_8859_7, "iso88597" },
725 { PG_ISO_8859_8, "ISO-8859-8" },
726 { PG_ISO_8859_8, "ISO8859-8" },
727 { PG_ISO_8859_8, "iso88598" },
729 { PG_SQL_ASCII, NULL } /* end marker */
733 get_encoding_from_locale(const char *ctype)
738 save = setlocale(LC_CTYPE, NULL);
741 save = xstrdup(save);
743 setlocale(LC_CTYPE, ctype);
744 sys = nl_langinfo(CODESET);
747 setlocale(LC_CTYPE, save);
754 check_encodings_match(int pg_enc, const char *ctype)
759 sys = get_encoding_from_locale(ctype);
761 for (i = 0; encoding_match_list[i].system_enc_name; i++)
763 if (pg_enc == encoding_match_list[i].pg_enc_code
764 && strcasecmp(sys, encoding_match_list[i].system_enc_name) == 0)
772 _("%s: warning: encoding mismatch\n"), progname);
774 _("The encoding you selected (%s) and the encoding that the selected\n"
775 "locale uses (%s) are not known to match. This may lead to\n"
776 "misbehavior in various character string processing functions. To fix\n"
777 "this situation, rerun %s and either do not specify an encoding\n"
778 "explicitly, or choose a matching combination.\n"),
779 pg_encoding_to_char(pg_enc), sys, progname);
786 find_matching_encoding(const char *ctype)
791 sys = get_encoding_from_locale(ctype);
793 for (i = 0; encoding_match_list[i].system_enc_name; i++)
795 if (strcasecmp(sys, encoding_match_list[i].system_enc_name) == 0)
798 return encoding_match_list[i].pg_enc_code;
805 #endif /* HAVE_LANGINFO_H && CODESET */
808 * get short version of VERSION
811 get_short_version(void)
817 vr = xstrdup(PG_VERSION);
819 for (end = 0; vr[end] != '\0'; end++)
830 else if (vr[end] < '0' || vr[end] > '9')
832 /* gone past digits and dots */
836 if (end == 0 || vr[end - 1] == '.' || !gotdot)
844 * make sure the data directory either doesn't exist or is empty
846 * Returns 0 if nonexistent, 1 if exists and empty, 2 if not empty,
847 * or -1 if trouble accessing directory
858 chkdir = opendir(pg_data);
861 return (errno == ENOENT) ? 0 : -1;
863 while ((file = readdir(chkdir)) != NULL)
865 if (strcmp(".", file->d_name) == 0 || strcmp("..", file->d_name) == 0)
867 /* skip this and parent directory */
872 result = 2; /* not empty */
880 result = -1; /* some kind of I/O error? */
886 * make the data directory (or one of its subdirectories if subdir is not NULL)
889 mkdatadir(const char *subdir)
893 path = xmalloc(strlen(pg_data) + 2 +
894 (subdir == NULL ? 0 : strlen(subdir)));
897 sprintf(path, "%s/%s", pg_data, subdir);
899 strcpy(path, pg_data);
901 return (mkdir_p(path, 0700) == 0);
906 * set name of given input file variable under data directory
909 set_input(char **dest, char *filename)
911 *dest = xmalloc(strlen(share_path) + strlen(filename) + 2);
912 sprintf(*dest, "%s/%s", share_path, filename);
916 * check that given input file exists
919 check_input(char *path)
923 if (stat(path, &statbuf) != 0 || !S_ISREG(statbuf.st_mode))
926 _("%s: file \"%s\" does not exist\n"
927 "This means you have a corrupted installation or identified\n"
928 "the wrong directory with the invocation option -L.\n"),
936 * write out the PG_VERSION file in the data dir, or its subdirectory
937 * if extrapath is not NULL
940 set_short_version(char *short_version, char *extrapath)
945 if (extrapath == NULL)
947 path = xmalloc(strlen(pg_data) + 12);
948 sprintf(path, "%s/PG_VERSION", pg_data);
952 path = xmalloc(strlen(pg_data) + strlen(extrapath) + 13);
953 sprintf(path, "%s/%s/PG_VERSION", pg_data, extrapath);
955 version_file = fopen(path, PG_BINARY_W);
956 if (version_file == NULL)
958 fprintf(version_file, "%s\n", short_version);
959 if (fclose(version_file))
964 * set up an empty config file so we can check buffers and connections
972 path = xmalloc(strlen(pg_data) + 17);
973 sprintf(path, "%s/postgresql.conf", pg_data);
974 conf_file = fopen(path, PG_BINARY_W);
975 if (conf_file == NULL || fclose(conf_file))
980 * check how many connections we can sustain
983 test_connections(void)
986 static const int conns[] = {100, 50, 40, 30, 20, 10};
987 static const int len = sizeof(conns) / sizeof(int);
991 printf(_("selecting default max_connections ... "));
994 for (i = 0; i < len; i++)
996 snprintf(cmd, sizeof(cmd),
997 "%s\"%s\" -boot -x0 %s "
998 "-c shared_buffers=%d -c max_connections=%d template1 "
999 "< \"%s\" > \"%s\" 2>&1%s",
1000 SYSTEMQUOTE, backend_exec, boot_options,
1001 conns[i] * 5, conns[i],
1002 DEVNULL, DEVNULL, SYSTEMQUOTE);
1003 status = system(cmd);
1009 n_connections = conns[i];
1011 printf("%d\n", n_connections);
1015 * check how many buffers we can run with
1020 char cmd[MAXPGPATH];
1021 static const int bufs[] = {1000, 900, 800, 700, 600, 500,
1022 400, 300, 200, 100, 50};
1023 static const int len = sizeof(bufs) / sizeof(int);
1027 printf(_("selecting default shared_buffers ... "));
1030 for (i = 0; i < len; i++)
1032 snprintf(cmd, sizeof(cmd),
1033 "%s\"%s\" -boot -x0 %s "
1034 "-c shared_buffers=%d -c max_connections=%d template1 "
1035 "< \"%s\" > \"%s\" 2>&1%s",
1036 SYSTEMQUOTE, backend_exec, boot_options,
1037 bufs[i], n_connections,
1038 DEVNULL, DEVNULL, SYSTEMQUOTE);
1039 status = system(cmd);
1045 n_buffers = bufs[i];
1047 printf("%d\n", n_buffers);
1051 * set up all the config files
1058 char path[MAXPGPATH];
1060 fputs(_("creating configuration files ... "), stdout);
1063 /* postgresql.conf */
1065 conflines = readfile(conf_file);
1067 snprintf(repltok, sizeof(repltok), "max_connections = %d", n_connections);
1068 conflines = replace_token(conflines, "#max_connections = 100", repltok);
1070 snprintf(repltok, sizeof(repltok), "shared_buffers = %d", n_buffers);
1071 conflines = replace_token(conflines, "#shared_buffers = 1000", repltok);
1073 snprintf(repltok, sizeof(repltok), "lc_messages = '%s'", lc_messages);
1074 conflines = replace_token(conflines, "#lc_messages = 'C'", repltok);
1076 snprintf(repltok, sizeof(repltok), "lc_monetary = '%s'", lc_monetary);
1077 conflines = replace_token(conflines, "#lc_monetary = 'C'", repltok);
1079 snprintf(repltok, sizeof(repltok), "lc_numeric = '%s'", lc_numeric);
1081 conflines = replace_token(conflines, "#lc_numeric = 'C'", repltok);
1083 snprintf(repltok, sizeof(repltok), "lc_time = '%s'", lc_time);
1084 conflines = replace_token(conflines, "#lc_time = 'C'", repltok);
1086 snprintf(path, sizeof(path), "%s/postgresql.conf", pg_data);
1088 writefile(path, conflines);
1096 conflines = readfile(hba_file);
1099 conflines = replace_token(conflines,
1101 "#host all all ::1");
1104 /* Replace default authentication methods */
1105 conflines = replace_token(conflines,
1109 conflines = replace_token(conflines,
1111 strcmp(authmethod,"trust") ? "" : authtrust_warning);
1113 snprintf(path, sizeof(path), "%s/pg_hba.conf", pg_data);
1115 writefile(path, conflines);
1122 conflines = readfile(ident_file);
1124 snprintf(path, sizeof(path), "%s/pg_ident.conf", pg_data);
1126 writefile(path, conflines);
1136 * run the BKI script in bootstrap mode to create template1
1139 bootstrap_template1(char *short_version)
1141 char *talkargs = "";
1143 char headerline[MAXPGPATH];
1147 printf(_("creating template1 database in %s/base/1 ... "), pg_data);
1153 bki_lines = readfile(bki_file);
1155 /* Check that bki file appears to be of the right version */
1157 snprintf(headerline, sizeof(headerline), "# PostgreSQL %s\n",
1160 if (strcmp(headerline, *bki_lines) != 0)
1163 _("%s: input file \"%s\" does not belong to PostgreSQL %s\n"
1164 "Check your installation or specify the correct path "
1165 "using the option -L.\n"),
1166 progname, bki_file, PG_VERSION);
1171 bki_lines = replace_token(bki_lines, "POSTGRES", effective_user);
1173 bki_lines = replace_token(bki_lines, "ENCODING", encodingid);
1176 * Pass correct LC_xxx environment to bootstrap.
1178 * The shell script arranged to restore the LC settings afterwards,
1179 * but there doesn't seem to be any compelling reason to do that.
1181 snprintf(cmd, sizeof(cmd), "LC_COLLATE=%s", lc_collate);
1182 putenv(xstrdup(cmd));
1184 snprintf(cmd, sizeof(cmd), "LC_CTYPE=%s", lc_ctype);
1185 putenv(xstrdup(cmd));
1189 /* Also ensure backend isn't confused by this environment var: */
1190 unsetenv("PGCLIENTENCODING");
1192 snprintf(cmd, sizeof(cmd),
1193 "\"%s\" -boot -x1 %s %s template1",
1194 backend_exec, boot_options, talkargs);
1198 for (line = bki_lines; *line != NULL; line++)
1212 * set up the shadow password table
1217 char *pg_shadow_setup[] = {
1219 * Create a trigger so that direct updates to pg_shadow will be
1220 * written to the flat password/group files pg_pwd and pg_group
1222 "CREATE TRIGGER pg_sync_pg_pwd "
1223 " AFTER INSERT OR UPDATE OR DELETE ON pg_shadow "
1224 " FOR EACH ROW EXECUTE PROCEDURE update_pg_pwd_and_pg_group();\n",
1225 "CREATE TRIGGER pg_sync_pg_group "
1226 " AFTER INSERT OR UPDATE OR DELETE ON pg_group "
1227 " FOR EACH ROW EXECUTE PROCEDURE update_pg_pwd_and_pg_group();\n",
1230 * needs to be done before alter user, because alter user checks
1231 * that pg_shadow is secure ...
1233 "REVOKE ALL on pg_shadow FROM public;\n",
1239 fputs(_("initializing pg_shadow ... "), stdout);
1242 snprintf(cmd, sizeof(cmd),
1243 "\"%s\" %s template1 >%s",
1244 backend_exec, backend_options,
1249 for (line = pg_shadow_setup; *line != NULL; line++)
1258 * get the superuser password if required, and call postgres to set it
1267 char pwdpath[MAXPGPATH];
1268 struct stat statbuf;
1273 * Read password from terminal
1275 pwd1 = simple_prompt("Enter new superuser password: ", 100, false);
1276 pwd2 = simple_prompt("Enter it again: ", 100, false);
1277 if (strcmp(pwd1, pwd2) != 0)
1279 fprintf(stderr, _("Passwords didn't match.\n"));
1287 * Read password from file
1289 * Ideally this should insist that the file not be world-readable.
1290 * However, this option is mainly intended for use on Windows where
1291 * file permissions may not exist at all, so we'll skip the paranoia
1294 FILE *pwf = fopen(pwfilename,"r");
1295 char pwdbuf[MAXPGPATH];
1300 fprintf(stderr, _("%s: could not open file \"%s\" for reading: %s\n"),
1301 progname, pwfilename, strerror(errno));
1304 if (!fgets(pwdbuf, sizeof(pwdbuf), pwf))
1306 fprintf(stderr, _("%s: could not read password from file \"%s\": %s\n"),
1307 progname, pwfilename, strerror(errno));
1313 while (i > 0 && (pwdbuf[i-1] == '\r' || pwdbuf[i-1] == '\n'))
1316 pwd1 = xstrdup(pwdbuf);
1319 printf(_("setting password ... "));
1322 snprintf(cmd, sizeof(cmd),
1323 "\"%s\" %s template1 >%s",
1324 backend_exec, backend_options,
1330 "ALTER USER \"%s\" WITH PASSWORD '%s';\n", effective_user, pwd1) < 0)
1339 snprintf(pwdpath, sizeof(pwdpath), "%s/global/pg_pwd", pg_data);
1340 if (stat(pwdpath, &statbuf) != 0 || !S_ISREG(statbuf.st_mode))
1343 _("%s: The password file was not generated. "
1344 "Please report this problem.\n"),
1356 unlimit_systables(void)
1358 char *systables_setup[] = {
1359 "ALTER TABLE pg_attrdef CREATE TOAST TABLE;\n",
1360 "ALTER TABLE pg_constraint CREATE TOAST TABLE;\n",
1361 "ALTER TABLE pg_database CREATE TOAST TABLE;\n",
1362 "ALTER TABLE pg_description CREATE TOAST TABLE;\n",
1363 "ALTER TABLE pg_group CREATE TOAST TABLE;\n",
1364 "ALTER TABLE pg_proc CREATE TOAST TABLE;\n",
1365 "ALTER TABLE pg_rewrite CREATE TOAST TABLE;\n",
1366 "ALTER TABLE pg_shadow CREATE TOAST TABLE;\n",
1367 "ALTER TABLE pg_statistic CREATE TOAST TABLE;\n",
1373 fputs(_("enabling unlimited row size for system tables ... "), stdout);
1376 snprintf(cmd, sizeof(cmd),
1377 "\"%s\" %s template1 >%s",
1378 backend_exec, backend_options,
1383 for (line = systables_setup; *line != NULL; line++)
1397 char *pg_depend_setup[] = {
1399 * Make PIN entries in pg_depend for all objects made so far in
1400 * the tables that the dependency code handles. This is overkill
1401 * (the system doesn't really depend on having every last weird
1402 * datatype, for instance) but generating only the minimum
1403 * required set of dependencies seems hard.
1405 * Note that we deliberately do not pin the system views, which
1406 * haven't been created yet.
1408 * First delete any already-made entries; PINs override all else, and
1409 * must be the only entries for their objects.
1411 "DELETE FROM pg_depend;\n",
1412 "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' "
1413 " FROM pg_class;\n",
1414 "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' "
1416 "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' "
1418 "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' "
1420 "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' "
1421 " FROM pg_constraint;\n",
1422 "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' "
1423 " FROM pg_attrdef;\n",
1424 "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' "
1425 " FROM pg_language;\n",
1426 "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' "
1427 " FROM pg_operator;\n",
1428 "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' "
1429 " FROM pg_opclass;\n",
1430 "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' "
1431 " FROM pg_rewrite;\n",
1432 "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' "
1433 " FROM pg_trigger;\n",
1436 * restriction here to avoid pinning the public namespace
1438 "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' "
1439 " FROM pg_namespace "
1440 " WHERE nspname LIKE 'pg%';\n",
1446 fputs(_("initializing pg_depend ... "), stdout);
1449 snprintf(cmd, sizeof(cmd),
1450 "\"%s\" %s template1 >%s",
1451 backend_exec, backend_options,
1456 for (line = pg_depend_setup; *line != NULL; line++)
1465 * set up system views
1468 setup_sysviews(void)
1472 char **sysviews_setup;
1474 fputs(_("creating system views ... "), stdout);
1477 sysviews_setup = readfile(system_views_file);
1480 * We use -N here to avoid backslashing stuff in system_views.sql
1482 snprintf(cmd, sizeof(cmd),
1483 "\"%s\" %s -N template1 >%s",
1484 backend_exec, backend_options,
1489 for (line = sysviews_setup; *line != NULL; line++)
1497 free(sysviews_setup);
1503 * load description data
1506 setup_description(void)
1511 fputs(_("loading pg_description ... "), stdout);
1514 snprintf(cmd, sizeof(cmd),
1515 "\"%s\" %s template1 >%s",
1516 backend_exec, backend_options,
1522 "CREATE TEMP TABLE tmp_pg_description ( "
1526 " description text) WITHOUT OIDS;\n");
1531 "COPY tmp_pg_description FROM '%s';\n",
1537 "INSERT INTO pg_description "
1538 " SELECT t.objoid, c.oid, t.objsubid, t.description "
1539 " FROM tmp_pg_description t, pg_class c "
1540 " WHERE c.relname = t.classname;\n");
1550 * load conversion functions
1553 setup_conversion(void)
1559 fputs(_("creating conversions ... "), stdout);
1562 snprintf(cmd, sizeof(cmd),
1563 "\"%s\" %s template1 >%s",
1564 backend_exec, backend_options,
1569 conv_lines = readfile(conversion_file);
1570 for (line = conv_lines; *line != NULL; line++)
1572 if (strstr(*line, "DROP CONVERSION") != *line)
1588 * We set most system catalogs and built-in functions as world-accessible.
1589 * Some objects may require different permissions by default, so we
1590 * make sure we don't overwrite privilege sets that have already been
1594 setup_privileges(void)
1596 char *privileges_setup[] = {
1598 " SET relacl = '{\"=r/\\\\\"$POSTGRES_SUPERUSERNAME\\\\\"\"}' "
1599 " WHERE relkind IN ('r', 'v', 'S') AND relacl IS NULL;\n",
1601 " SET proacl = '{\"=X/\\\\\"$POSTGRES_SUPERUSERNAME\\\\\"\"}' "
1602 " WHERE proacl IS NULL;\n",
1603 "UPDATE pg_language "
1604 " SET lanacl = '{\"=U/\\\\\"$POSTGRES_SUPERUSERNAME\\\\\"\"}' "
1605 " WHERE lanpltrusted;\n",
1606 "GRANT USAGE ON SCHEMA pg_catalog TO PUBLIC;\n",
1607 "GRANT CREATE, USAGE ON SCHEMA public TO PUBLIC;\n",
1615 fputs(_("setting privileges on built-in objects ... "), stdout);
1618 snprintf(cmd, sizeof(cmd),
1619 "\"%s\" %s template1 >%s",
1620 backend_exec, backend_options,
1625 priv_lines = replace_token(privileges_setup,
1626 "$POSTGRES_SUPERUSERNAME", effective_user);
1627 for (line = priv_lines; *line != NULL; line++)
1636 * extract the strange version of version required for information schema
1640 set_info_version(void)
1642 char *letterversion;
1647 char *vstr = xstrdup(PG_VERSION);
1650 ptr = vstr + (strlen(vstr) - 1);
1651 while (ptr != vstr && (*ptr < '0' || *ptr > '9'))
1653 letterversion = ptr + 1;
1654 major = strtol(vstr, &endptr, 10);
1656 minor = strtol(endptr + 1, &endptr, 10);
1658 micro = strtol(endptr + 1, &endptr, 10);
1659 snprintf(infoversion, sizeof(infoversion), "%02ld.%02ld.%04ld%s",
1660 major, minor, micro, letterversion);
1664 * load info schema and populate from features file
1673 fputs(_("creating information schema ... "), stdout);
1676 lines = readfile(info_schema_file);
1679 * We use -N here to avoid backslashing stuff in information_schema.sql
1681 snprintf(cmd, sizeof(cmd),
1682 "\"%s\" %s -N template1 >%s",
1683 backend_exec, backend_options,
1688 for (line = lines; *line != NULL; line++)
1698 snprintf(cmd, sizeof(cmd),
1699 "\"%s\" %s template1 >%s",
1700 backend_exec, backend_options,
1706 "UPDATE information_schema.sql_implementation_info "
1707 " SET character_value = '%s' "
1708 " WHERE implementation_info_name = 'DBMS VERSION';\n",
1714 "COPY information_schema.sql_features "
1715 " (feature_id, feature_name, sub_feature_id, "
1716 " sub_feature_name, is_supported, comments) "
1728 * clean everything up in template1
1735 fputs(_("vacuuming database template1 ... "), stdout);
1738 snprintf(cmd, sizeof(cmd),
1739 "\"%s\" %s template1 >%s",
1740 backend_exec, backend_options,
1745 if (fputs("ANALYZE;\nVACUUM FULL FREEZE;\n", pg) < 0)
1755 * copy template1 to template0
1758 make_template0(void)
1760 char *template0_setup[] = {
1761 "CREATE DATABASE template0;\n",
1762 "UPDATE pg_database SET "
1763 " datistemplate = 't', "
1764 " datallowconn = 'f' "
1765 " WHERE datname = 'template0';\n",
1768 * We use the OID of template0 to determine lastsysoid
1770 "UPDATE pg_database SET datlastsysoid = "
1771 " (SELECT oid::int4 - 1 FROM pg_database "
1772 " WHERE datname = 'template0');\n",
1775 * Explicitly revoke public create-schema and create-temp-table
1776 * privileges in template1 and template0; else the latter would be
1779 "REVOKE CREATE,TEMPORARY ON DATABASE template1 FROM public;\n",
1780 "REVOKE CREATE,TEMPORARY ON DATABASE template0 FROM public;\n",
1783 * Finally vacuum to clean up dead rows in pg_database
1785 "VACUUM FULL pg_database;\n",
1791 fputs(_("copying template1 to template0 ... "), stdout);
1794 snprintf(cmd, sizeof(cmd),
1795 "\"%s\" %s template1 >%s",
1796 backend_exec, backend_options,
1801 for (line = template0_setup; *line; line++)
1811 * signal handler in case we are interrupted.
1813 * The Windows runtime docs at
1814 * http://msdn.microsoft.com/library/en-us/vclib/html/_crt_signal.asp
1815 * specifically forbid a number of things being done from a signal handler,
1816 * including IO, memory allocation and system calls, and only allow jmpbuf
1817 * if you are handling SIGFPE.
1819 * I avoided doing the forbidden things by setting a flag instead of calling
1820 * exit_nicely() directly.
1822 * Also note the behaviour of Windows with SIGINT, which says this:
1823 * Note SIGINT is not supported for any Win32 application, including
1824 * Windows 98/Me and Windows NT/2000/XP. When a CTRL+C interrupt occurs,
1825 * Win32 operating systems generate a new thread to specifically handle
1826 * that interrupt. This can cause a single-thread application such as UNIX,
1827 * to become multithreaded, resulting in unexpected behavior.
1829 * I have no idea how to handle this. (Strange they call UNIX an application!)
1830 * So this will need some testing on Windows.
1835 /* handle systems that reset the handler, like Windows (grr) */
1836 pqsignal(signum, trapsig);
1837 caught_signal = true;
1841 * call exit_nicely() if we got a signal, or else output "ok".
1848 printf(_("caught signal\n"));
1851 else if (output_failed)
1853 printf(_("could not write to child process\n"));
1858 /* all seems well */
1865 * check if given string is a valid locale specifier
1866 * based on some code given to me by Peter Eisentraut
1867 * (but I take responsibility for it :-)
1870 chklocale(const char *locale)
1873 int category = LC_CTYPE;
1876 save = setlocale(category, NULL);
1878 return false; /* should not happen; */
1880 save = xstrdup(save);
1882 ret = (setlocale(category, locale) != NULL);
1884 setlocale(category, save);
1887 /* should we exit here? */
1889 fprintf(stderr, _("%s: invalid locale name \"%s\"\n"), progname, locale);
1895 * set up the locale variables
1897 * assumes we have called setlocale(LC_ALL,"")
1902 /* set empty lc_* values to locale config if set */
1904 if (strlen(locale) > 0)
1906 if (strlen(lc_ctype) == 0)
1908 if (strlen(lc_collate) == 0)
1909 lc_collate = locale;
1910 if (strlen(lc_numeric) == 0)
1911 lc_numeric = locale;
1912 if (strlen(lc_time) == 0)
1914 if (strlen(lc_monetary) == 0)
1915 lc_monetary = locale;
1916 if (strlen(lc_messages) == 0)
1917 lc_messages = locale;
1921 * override absent/invalid config settings from initdb's locale
1925 if (strlen(lc_ctype) == 0 || !chklocale(lc_ctype))
1926 lc_ctype = xstrdup(setlocale(LC_CTYPE, NULL));
1927 if (strlen(lc_collate) == 0 || !chklocale(lc_collate))
1928 lc_collate = xstrdup(setlocale(LC_COLLATE, NULL));
1929 if (strlen(lc_numeric) == 0 || !chklocale(lc_numeric))
1930 lc_numeric = xstrdup(setlocale(LC_NUMERIC, NULL));
1931 if (strlen(lc_time) == 0 || !chklocale(lc_time))
1932 lc_time = xstrdup(setlocale(LC_TIME, NULL));
1933 if (strlen(lc_monetary) == 0 || !chklocale(lc_monetary))
1934 lc_monetary = xstrdup(setlocale(LC_MONETARY, NULL));
1935 if (strlen(lc_messages) == 0 || !chklocale(lc_messages))
1938 /* when available get the current locale setting */
1939 lc_messages = xstrdup(setlocale(LC_MESSAGES, NULL));
1943 /* when not available, get the CTYPE setting */
1944 lc_messages = xstrdup(setlocale(LC_CTYPE, NULL));
1954 usage(const char *progname)
1956 printf(_("%s initializes a PostgreSQL database cluster.\n\n"), progname);
1957 printf(_("Usage:\n"));
1958 printf(_(" %s [OPTION]... [DATADIR]\n"), progname);
1959 printf(_("\nOptions:\n"));
1960 printf(_(" [-D, --pgdata=]DATADIR location for this database cluster\n"));
1961 printf(_(" -E, --encoding=ENCODING set default encoding for new databases\n"));
1962 printf(_(" --locale=LOCALE initialize database cluster with given locale\n"));
1963 printf(_(" --lc-collate, --lc-ctype, --lc-messages=LOCALE\n"
1964 " --lc-monetary, --lc-numeric, --lc-time=LOCALE\n"
1965 " initialize database cluster with given locale\n"
1966 " in the respective category (default taken from\n"
1967 " environment)\n"));
1968 printf(_(" --no-locale equivalent to --locale=C\n"));
1969 printf(_(" -A, --auth=method default authentication method for local connections\n"));
1970 printf(_(" -U, --username=NAME database superuser name\n"));
1971 printf(_(" -W, --pwprompt prompt for a password for the new superuser\n"));
1972 printf(_(" --pwfile=filename read password for the new superuser from file\n"));
1973 printf(_(" -?, --help show this help, then exit\n"));
1974 printf(_(" -V, --version output version information, then exit\n"));
1975 printf(_("\nLess commonly used options:\n"));
1976 printf(_(" -d, --debug generate lots of debugging output\n"));
1977 printf(_(" -s, --show show internal settings\n"));
1978 printf(_(" -L DIRECTORY where to find the input files\n"));
1979 printf(_(" -n, --noclean do not clean up after errors\n"));
1980 printf(_("\nIf the data directory is not specified, the environment variable PGDATA\n"
1982 printf(_("\nReport bugs to <pgsql-bugs@postgresql.org>.\n"));
1986 main(int argc, char *argv[])
1989 * options with no short version return a low integer, the rest return
1990 * their short version value
1992 static struct option long_options[] = {
1993 {"pgdata", required_argument, NULL, 'D'},
1994 {"encoding", required_argument, NULL, 'E'},
1995 {"locale", required_argument, NULL, 1},
1996 {"lc-collate", required_argument, NULL, 2},
1997 {"lc-ctype", required_argument, NULL, 3},
1998 {"lc-monetary", required_argument, NULL, 4},
1999 {"lc-numeric", required_argument, NULL, 5},
2000 {"lc-time", required_argument, NULL, 6},
2001 {"lc-messages", required_argument, NULL, 7},
2002 {"no-locale", no_argument, NULL, 8},
2003 {"auth", required_argument, NULL, 'A'},
2004 {"pwprompt", no_argument, NULL, 'W'},
2005 {"pwfile", required_argument, NULL, 9},
2006 {"username", required_argument, NULL, 'U'},
2007 {"help", no_argument, NULL, '?'},
2008 {"version", no_argument, NULL, 'V'},
2009 {"debug", no_argument, NULL, 'd'},
2010 {"show", no_argument, NULL, 's'},
2011 {"noclean", no_argument, NULL, 'n'},
2019 char *short_version;
2020 char *pgdenv; /* PGDATA value got from sent to
2022 static const char *subdirs[] = {
2025 "pg_xlog/archive_status",
2033 progname = get_progname(argv[0]);
2034 set_pglocale_pgservice(argv[0], "initdb");
2038 if (strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-?") == 0)
2043 if (strcmp(argv[1], "--version") == 0 || strcmp(argv[1], "-V") == 0)
2045 puts("initdb (PostgreSQL) " PG_VERSION);
2050 /* process command-line options */
2052 while ((c = getopt_long(argc, argv, "dD:E:L:nU:WA:", long_options, &option_index)) != -1)
2057 authmethod = xstrdup(optarg);
2060 pg_data = xstrdup(optarg);
2063 encoding = xstrdup(optarg);
2069 username = xstrdup(optarg);
2073 printf(_("Running in debug mode.\n"));
2077 printf(_("Running in noclean mode. Mistakes will not be cleaned up.\n"));
2080 share_path = xstrdup(optarg);
2083 locale = xstrdup(optarg);
2086 lc_collate = xstrdup(optarg);
2089 lc_ctype = xstrdup(optarg);
2092 lc_monetary = xstrdup(optarg);
2095 lc_numeric = xstrdup(optarg);
2098 lc_time = xstrdup(optarg);
2101 lc_messages = xstrdup(optarg);
2107 pwfilename = xstrdup(optarg);
2110 show_setting = true;
2113 fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
2119 /* Non-option argument specifies data directory */
2122 pg_data = xstrdup(argv[optind]);
2128 fprintf(stderr, _("%s: too many command-line arguments (first is \"%s\")\n"),
2129 progname, argv[optind + 1]);
2130 fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
2134 if (pwprompt && pwfilename)
2136 fprintf(stderr, _("%s: you cannot specify both password prompt and password file\n"), progname);
2140 if (authmethod == NULL || !strlen(authmethod))
2142 authwarning = _("\nWARNING: enabling \"trust\" authentication for local connections.\n"
2143 "You can change this by editing pg_hba.conf or using the -A flag the\n"
2144 "next time you run initdb.\n");
2148 if (strcmp(authmethod,"md5") &&
2149 strcmp(authmethod,"ident") &&
2150 strncmp(authmethod,"ident ",6) && /* ident with space = param */
2151 strcmp(authmethod,"trust") &&
2153 strcmp(authmethod,"pam") &&
2154 strncmp(authmethod,"pam ",4) && /* pam with space = param */
2156 strcmp(authmethod,"crypt") &&
2157 strcmp(authmethod,"password")
2160 * Kerberos methods not listed because they are not supported
2161 * over local connections and are rejected in hba.c
2164 fprintf(stderr, _("%s: unknown authentication method \"%s\".\n"), progname, authmethod);
2168 if ((!strcmp(authmethod,"md5") ||
2169 !strcmp(authmethod,"crypt") ||
2170 !strcmp(authmethod,"password")) &&
2171 !(pwprompt || pwfilename))
2173 fprintf(stderr, _("%s: you need to specify a password for the superuser to enable %s authentication.\n"), progname, authmethod);
2177 if (strlen(pg_data) == 0)
2179 pgdenv = getenv("PGDATA");
2180 if (pgdenv && strlen(pgdenv))
2183 pg_data = xstrdup(pgdenv);
2188 _("%s: no data directory specified\n"
2189 "You must identify the directory where the data for this database system\n"
2190 "will reside. Do this with either the invocation option -D or the\n"
2191 "environment variable PGDATA.\n"),
2197 canonicalize_path(pg_data);
2200 * we have to set PGDATA for postgres rather than pass it on the
2201 * commnd line to avoid dumb quoting problems on Windows, and we would
2202 * expecially need quotes otherwise on Windows because paths there are
2203 * most likely to have embedded spaces.
2205 pgdenv = xmalloc(8 + strlen(pg_data));
2206 sprintf(pgdenv, "PGDATA=%s", pg_data);
2209 if ((ret = find_other_exec(argv[0], "postgres", PG_VERSIONSTR,
2214 _("The program \"postgres\" is needed by %s "
2215 "but was not found in the same directory as \"%s\".\n"
2216 "Check your installation.\n"),
2217 progname, progname);
2220 _("The program \"postgres\" was found by %s "
2221 "but was not the same version as \"%s\".\n"
2222 "Check your installation.\n"),
2223 progname, progname);
2227 /* store binary directory */
2228 strcpy(bin_path, backend_exec);
2229 *last_dir_separator(bin_path) = '\0';
2230 canonicalize_path(bin_path);
2234 share_path = xmalloc(MAXPGPATH);
2235 get_share_path(backend_exec, share_path);
2238 canonicalize_path(share_path);
2240 if ((short_version = get_short_version()) == NULL)
2242 fprintf(stderr, _("%s: could not determine valid short version string\n"), progname);
2246 if (strlen(username))
2247 effective_user = username;
2249 effective_user = get_id();
2251 if (strlen(encoding))
2252 encodingid = get_encoding_id(encoding);
2254 set_input(&bki_file, "postgres.bki");
2255 set_input(&desc_file, "postgres.description");
2256 set_input(&hba_file, "pg_hba.conf.sample");
2257 set_input(&ident_file, "pg_ident.conf.sample");
2258 set_input(&conf_file, "postgresql.conf.sample");
2259 set_input(&conversion_file, "conversion_create.sql");
2260 set_input(&info_schema_file, "information_schema.sql");
2261 set_input(&features_file, "sql_features.txt");
2262 set_input(&system_views_file, "system_views.sql");
2266 if (show_setting || debug)
2270 "PGDATA=%s\nshare_path=%s\nPGPATH=%s\n"
2271 "POSTGRES_SUPERUSERNAME=%s\nPOSTGRES_BKI=%s\n"
2272 "POSTGRES_DESCR=%s\nPOSTGRESQL_CONF_SAMPLE=%s\n"
2273 "PG_HBA_SAMPLE=%s\nPG_IDENT_SAMPLE=%s\n",
2275 pg_data, share_path, bin_path,
2276 effective_user, bki_file,
2277 desc_file, conf_file,
2278 hba_file, ident_file);
2283 check_input(bki_file);
2284 check_input(desc_file);
2285 check_input(hba_file);
2286 check_input(ident_file);
2287 check_input(conf_file);
2288 check_input(conversion_file);
2289 check_input(info_schema_file);
2290 check_input(features_file);
2291 check_input(system_views_file);
2295 printf(_("The files belonging to this database system will be owned "
2297 "This user must also own the server process.\n\n"),
2300 if (strcmp(lc_ctype, lc_collate) == 0 &&
2301 strcmp(lc_ctype, lc_time) == 0 &&
2302 strcmp(lc_ctype, lc_numeric) == 0 &&
2303 strcmp(lc_ctype, lc_monetary) == 0 &&
2304 strcmp(lc_ctype, lc_messages) == 0)
2306 printf(_("The database cluster will be initialized with locale %s.\n"), lc_ctype);
2310 printf(_("The database cluster will be initialized with locales\n"
2325 #if defined(HAVE_LANGINFO_H) && defined(CODESET)
2326 if (strcmp(lc_ctype, "C") != 0 && strcmp(lc_ctype, "POSIX") != 0)
2328 if (strlen(encoding) == 0)
2331 tmp = find_matching_encoding(lc_ctype);
2334 fprintf(stderr, _("%s: could not find suitable encoding for locale \"%s\"\n"), progname, lc_ctype);
2335 fprintf(stderr, _("Rerun %s with the -E option.\n"), progname);
2336 fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
2341 encodingid = encodingid_to_string(tmp);
2342 printf(_("The default database encoding has accordingly been set to %s.\n"),
2343 pg_encoding_to_char(tmp));
2347 check_encodings_match(atoi(encodingid), lc_ctype);
2349 #endif /* HAVE_LANGINFO_H && CODESET */
2356 * now we are starting to do real work, trap signals so we can clean
2360 /* some of these are not valid on Windows */
2362 pqsignal(SIGHUP, trapsig);
2365 pqsignal(SIGINT, trapsig);
2368 pqsignal(SIGQUIT, trapsig);
2371 pqsignal(SIGTERM, trapsig);
2374 /* Ignore SIGPIPE when writing to backend, so we can clean up */
2376 pqsignal(SIGPIPE, SIG_IGN);
2379 switch (check_data_dir())
2382 /* PGDATA not there, must create it */
2383 printf(_("creating directory %s ... "),
2387 if (!mkdatadir(NULL))
2392 made_new_pgdata = true;
2396 /* Present but empty, fix permissions and use it */
2397 printf(_("fixing permissions on existing directory %s ... "),
2401 if (chmod(pg_data, 0700) != 0)
2409 found_existing_pgdata = true;
2413 /* Present and not empty */
2415 _("%s: directory \"%s\" exists but is not empty\n"
2416 "If you want to create a new database system, either remove or empty\n"
2417 "the directory \"%s\" or run %s\n"
2418 "with an argument other than \"%s\".\n"),
2419 progname, pg_data, pg_data, progname, pg_data);
2420 exit(1); /* no further message needed */
2423 /* Trouble accessing directory */
2428 /* Create required subdirectories */
2430 for (i = 0; i < (sizeof(subdirs) / sizeof(char *)); i++)
2432 printf(_("creating directory %s/%s ... "), pg_data, subdirs[i]);
2435 if (!mkdatadir(subdirs[i]))
2441 /* Top level PG_VERSION is checked by bootstrapper, so make it first */
2442 set_short_version(short_version, NULL);
2445 * Determine platform-specific config settings
2447 * Use reasonable values if kernel will let us, else scale back. Probe for
2448 * max_connections first since it is subject to more constraints than
2457 /* Now create all the text config files */
2460 /* Bootstrap template1 */
2461 bootstrap_template1(short_version);
2463 /* Make the per-database PG_VERSION for template1 only after init'ing it */
2464 set_short_version(short_version, "base/1");
2466 /* Create the stuff we don't need to use bootstrap mode for */
2469 if (pwprompt || pwfilename)
2472 unlimit_systables();
2478 setup_description();
2490 if (authwarning != NULL)
2491 fprintf(stderr, authwarning);
2493 printf(_("\nSuccess. You can now start the database server using:\n\n"
2494 " %s%s%s/postmaster -D %s%s%s\n"
2496 " %s%s%s/pg_ctl -D %s%s%s -l logfile start\n\n"),
2497 QUOTE_PATH, bin_path, QUOTE_PATH, QUOTE_PATH, pg_data, QUOTE_PATH,
2498 QUOTE_PATH, bin_path, QUOTE_PATH, QUOTE_PATH, pg_data, QUOTE_PATH);