]> granicus.if.org Git - postgresql/blob - src/bin/initdb/initdb.c
Replace the XLogInsert slots with regular LWLocks.
[postgresql] / src / bin / initdb / initdb.c
1 /*-------------------------------------------------------------------------
2  *
3  * initdb --- initialize a PostgreSQL installation
4  *
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 server.
8  *
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 three databases: the
12  * template databases "template0" and "template1", and a default user
13  * database "postgres".
14  *
15  * The template databases are ordinary PostgreSQL databases.  template0
16  * is never supposed to change after initdb, whereas template1 can be
17  * changed to add site-local standard data.  Either one can be copied
18  * to produce a new database.
19  *
20  * For largely-historical reasons, the template1 database is the one built
21  * by the basic bootstrap process.      After it is complete, template0 and
22  * the default database, postgres, are made just by copying template1.
23  *
24  * To create template1, we run the postgres (backend) program in bootstrap
25  * mode and feed it data from the postgres.bki library file.  After this
26  * initial bootstrap phase, some additional stuff is created by normal
27  * SQL commands fed to a standalone backend.  Some of those commands are
28  * just embedded into this program (yeah, it's ugly), but larger chunks
29  * are taken from script files.
30  *
31  *
32  * Note:
33  *       The program has some memory leakage - it isn't worth cleaning it up.
34  *
35  * This is a C implementation of the previous shell script for setting up a
36  * PostgreSQL cluster location, and should be highly compatible with it.
37  * author of C translation: Andrew Dunstan         mailto:andrew@dunslane.net
38  *
39  * This code is released under the terms of the PostgreSQL License.
40  *
41  * Portions Copyright (c) 1996-2014, PostgreSQL Global Development Group
42  * Portions Copyright (c) 1994, Regents of the University of California
43  *
44  * src/bin/initdb/initdb.c
45  *
46  *-------------------------------------------------------------------------
47  */
48
49 #include "postgres_fe.h"
50
51 #include <dirent.h>
52 #include <fcntl.h>
53 #include <sys/stat.h>
54 #include <unistd.h>
55 #include <locale.h>
56 #include <signal.h>
57 #include <time.h>
58
59 #ifdef HAVE_SHM_OPEN
60 #include "sys/mman.h"
61 #endif
62
63 #include "common/username.h"
64 #include "mb/pg_wchar.h"
65 #include "getaddrinfo.h"
66 #include "getopt_long.h"
67 #include "miscadmin.h"
68
69 /* Ideally this would be in a .h file, but it hardly seems worth the trouble */
70 extern const char *select_default_timezone(const char *share_path);
71
72 static const char *auth_methods_host[] = {"trust", "reject", "md5", "password", "ident", "radius",
73 #ifdef ENABLE_GSS
74         "gss",
75 #endif
76 #ifdef ENABLE_SSPI
77         "sspi",
78 #endif
79 #ifdef USE_PAM
80         "pam", "pam ",
81 #endif
82 #ifdef USE_LDAP
83         "ldap",
84 #endif
85 #ifdef USE_SSL
86         "cert",
87 #endif
88 NULL};
89 static const char *auth_methods_local[] = {"trust", "reject", "md5", "password", "peer", "radius",
90 #ifdef USE_PAM
91         "pam", "pam ",
92 #endif
93 #ifdef USE_LDAP
94         "ldap",
95 #endif
96 NULL};
97
98 /*
99  * these values are passed in by makefile defines
100  */
101 static char *share_path = NULL;
102
103 /* values to be obtained from arguments */
104 static char *pg_data = "";
105 static char *encoding = "";
106 static char *locale = "";
107 static char *lc_collate = "";
108 static char *lc_ctype = "";
109 static char *lc_monetary = "";
110 static char *lc_numeric = "";
111 static char *lc_time = "";
112 static char *lc_messages = "";
113 static const char *default_text_search_config = "";
114 static char *username = "";
115 static bool pwprompt = false;
116 static char *pwfilename = NULL;
117 static const char *authmethodhost = "";
118 static const char *authmethodlocal = "";
119 static bool debug = false;
120 static bool noclean = false;
121 static bool do_sync = true;
122 static bool sync_only = false;
123 static bool show_setting = false;
124 static bool data_checksums = false;
125 static char *xlog_dir = "";
126
127
128 /* internal vars */
129 static const char *progname;
130 static char *encodingid = "0";
131 static char *bki_file;
132 static char *desc_file;
133 static char *shdesc_file;
134 static char *hba_file;
135 static char *ident_file;
136 static char *conf_file;
137 static char *conversion_file;
138 static char *dictionary_file;
139 static char *info_schema_file;
140 static char *features_file;
141 static char *system_views_file;
142 static bool made_new_pgdata = false;
143 static bool found_existing_pgdata = false;
144 static bool made_new_xlogdir = false;
145 static bool found_existing_xlogdir = false;
146 static char infoversion[100];
147 static bool caught_signal = false;
148 static bool output_failed = false;
149 static int      output_errno = 0;
150 static char *pgdata_native;
151
152 /* defaults */
153 static int      n_connections = 10;
154 static int      n_buffers = 50;
155 static char *dynamic_shared_memory_type = NULL;
156
157 /*
158  * Warning messages for authentication methods
159  */
160 #define AUTHTRUST_WARNING \
161 "# CAUTION: Configuring the system for local \"trust\" authentication\n" \
162 "# allows any local user to connect as any PostgreSQL user, including\n" \
163 "# the database superuser.  If you do not trust all your local users,\n" \
164 "# use another authentication method.\n"
165 static char *authwarning = NULL;
166
167 /*
168  * Centralized knowledge of switches to pass to backend
169  *
170  * Note: we run the backend with -F (fsync disabled) and then do a single
171  * pass of fsync'ing at the end.  This is faster than fsync'ing each step.
172  *
173  * Note: in the shell-script version, we also passed PGDATA as a -D switch,
174  * but here it is more convenient to pass it as an environment variable
175  * (no quoting to worry about).
176  */
177 static const char *boot_options = "-F";
178 static const char *backend_options = "--single -F -O -c search_path=pg_catalog -c exit_on_error=true";
179
180 #ifdef WIN32
181 char       *restrict_env;
182 #endif
183 static const char *subdirs[] = {
184         "global",
185         "pg_xlog",
186         "pg_xlog/archive_status",
187         "pg_clog",
188         "pg_dynshmem",
189         "pg_notify",
190         "pg_serial",
191         "pg_snapshots",
192         "pg_subtrans",
193         "pg_twophase",
194         "pg_multixact/members",
195         "pg_multixact/offsets",
196         "base",
197         "base/1",
198         "pg_replslot",
199         "pg_tblspc",
200         "pg_stat",
201         "pg_stat_tmp",
202         "pg_llog",
203         "pg_llog/snapshots",
204         "pg_llog/mappings"
205 };
206
207
208 /* path to 'initdb' binary directory */
209 static char bin_path[MAXPGPATH];
210 static char backend_exec[MAXPGPATH];
211
212 static char **replace_token(char **lines,
213                           const char *token, const char *replacement);
214
215 #ifndef HAVE_UNIX_SOCKETS
216 static char **filter_lines_with_token(char **lines, const char *token);
217 #endif
218 static char **readfile(const char *path);
219 static void writefile(char *path, char **lines);
220 static void walkdir(char *path, void (*action) (char *fname, bool isdir));
221 static void pre_sync_fname(char *fname, bool isdir);
222 static void fsync_fname(char *fname, bool isdir);
223 static FILE *popen_check(const char *command, const char *mode);
224 static void exit_nicely(void);
225 static char *get_id(void);
226 static char *get_encoding_id(char *encoding_name);
227 static bool mkdatadir(const char *subdir);
228 static void set_input(char **dest, char *filename);
229 static void check_input(char *path);
230 static void write_version_file(char *extrapath);
231 static void set_null_conf(void);
232 static void test_config_settings(void);
233 static void setup_config(void);
234 static void bootstrap_template1(void);
235 static void setup_auth(void);
236 static void get_set_pwd(void);
237 static void setup_depend(void);
238 static void setup_sysviews(void);
239 static void setup_description(void);
240 static void setup_collation(void);
241 static void setup_conversion(void);
242 static void setup_dictionary(void);
243 static void setup_privileges(void);
244 static void set_info_version(void);
245 static void setup_schema(void);
246 static void load_plpgsql(void);
247 static void vacuum_db(void);
248 static void make_template0(void);
249 static void make_postgres(void);
250 static void perform_fsync(void);
251 static void trapsig(int signum);
252 static void check_ok(void);
253 static char *escape_quotes(const char *src);
254 static int      locale_date_order(const char *locale);
255 static bool check_locale_name(int category, const char *locale,
256                                   char **canonname);
257 static bool check_locale_encoding(const char *locale, int encoding);
258 static void setlocales(void);
259 static void usage(const char *progname);
260 void            get_restricted_token(void);
261 void            setup_pgdata(void);
262 void            setup_bin_paths(const char *argv0);
263 void            setup_data_file_paths(void);
264 void            setup_locale_encoding(void);
265 void            setup_signals(void);
266 void            setup_text_search(void);
267 void            create_data_directory(void);
268 void            create_xlog_symlink(void);
269 void            warn_on_mount_point(int error);
270 void            initialize_data_directory(void);
271
272
273 #ifdef WIN32
274 static int      CreateRestrictedProcess(char *cmd, PROCESS_INFORMATION *processInfo);
275 #endif
276
277
278 /*
279  * macros for running pipes to postgres
280  */
281 #define PG_CMD_DECL             char cmd[MAXPGPATH]; FILE *cmdfd
282
283 #define PG_CMD_OPEN \
284 do { \
285         cmdfd = popen_check(cmd, "w"); \
286         if (cmdfd == NULL) \
287                 exit_nicely(); /* message already printed by popen_check */ \
288 } while (0)
289
290 #define PG_CMD_CLOSE \
291 do { \
292         if (pclose_check(cmdfd)) \
293                 exit_nicely(); /* message already printed by pclose_check */ \
294 } while (0)
295
296 #define PG_CMD_PUTS(line) \
297 do { \
298         if (fputs(line, cmdfd) < 0 || fflush(cmdfd) < 0) \
299                 output_failed = true, output_errno = errno; \
300 } while (0)
301
302 #define PG_CMD_PRINTF1(fmt, arg1) \
303 do { \
304         if (fprintf(cmdfd, fmt, arg1) < 0 || fflush(cmdfd) < 0) \
305                 output_failed = true, output_errno = errno; \
306 } while (0)
307
308 #define PG_CMD_PRINTF2(fmt, arg1, arg2) \
309 do { \
310         if (fprintf(cmdfd, fmt, arg1, arg2) < 0 || fflush(cmdfd) < 0) \
311                 output_failed = true, output_errno = errno; \
312 } while (0)
313
314 #define PG_CMD_PRINTF3(fmt, arg1, arg2, arg3)           \
315 do { \
316         if (fprintf(cmdfd, fmt, arg1, arg2, arg3) < 0 || fflush(cmdfd) < 0) \
317                 output_failed = true, output_errno = errno; \
318 } while (0)
319
320 #ifndef WIN32
321 #define QUOTE_PATH      ""
322 #define DIR_SEP "/"
323 #else
324 #define QUOTE_PATH      "\""
325 #define DIR_SEP "\\"
326 #endif
327
328 static char *
329 escape_quotes(const char *src)
330 {
331         char       *result = escape_single_quotes_ascii(src);
332
333         if (!result)
334         {
335                 fprintf(stderr, _("%s: out of memory\n"), progname);
336                 exit(1);
337         }
338         return result;
339 }
340
341 /*
342  * make a copy of the array of lines, with token replaced by replacement
343  * the first time it occurs on each line.
344  *
345  * This does most of what sed was used for in the shell script, but
346  * doesn't need any regexp stuff.
347  */
348 static char **
349 replace_token(char **lines, const char *token, const char *replacement)
350 {
351         int                     numlines = 1;
352         int                     i;
353         char      **result;
354         int                     toklen,
355                                 replen,
356                                 diff;
357
358         for (i = 0; lines[i]; i++)
359                 numlines++;
360
361         result = (char **) pg_malloc(numlines * sizeof(char *));
362
363         toklen = strlen(token);
364         replen = strlen(replacement);
365         diff = replen - toklen;
366
367         for (i = 0; i < numlines; i++)
368         {
369                 char       *where;
370                 char       *newline;
371                 int                     pre;
372
373                 /* just copy pointer if NULL or no change needed */
374                 if (lines[i] == NULL || (where = strstr(lines[i], token)) == NULL)
375                 {
376                         result[i] = lines[i];
377                         continue;
378                 }
379
380                 /* if we get here a change is needed - set up new line */
381
382                 newline = (char *) pg_malloc(strlen(lines[i]) + diff + 1);
383
384                 pre = where - lines[i];
385
386                 strncpy(newline, lines[i], pre);
387
388                 strcpy(newline + pre, replacement);
389
390                 strcpy(newline + pre + replen, lines[i] + pre + toklen);
391
392                 result[i] = newline;
393         }
394
395         return result;
396 }
397
398 /*
399  * make a copy of lines without any that contain the token
400  *
401  * a sort of poor man's grep -v
402  */
403 #ifndef HAVE_UNIX_SOCKETS
404 static char **
405 filter_lines_with_token(char **lines, const char *token)
406 {
407         int                     numlines = 1;
408         int                     i,
409                                 src,
410                                 dst;
411         char      **result;
412
413         for (i = 0; lines[i]; i++)
414                 numlines++;
415
416         result = (char **) pg_malloc(numlines * sizeof(char *));
417
418         for (src = 0, dst = 0; src < numlines; src++)
419         {
420                 if (lines[src] == NULL || strstr(lines[src], token) == NULL)
421                         result[dst++] = lines[src];
422         }
423
424         return result;
425 }
426 #endif
427
428 /*
429  * get the lines from a text file
430  */
431 static char **
432 readfile(const char *path)
433 {
434         FILE       *infile;
435         int                     maxlength = 1,
436                                 linelen = 0;
437         int                     nlines = 0;
438         int                     n;
439         char      **result;
440         char       *buffer;
441         int                     c;
442
443         if ((infile = fopen(path, "r")) == NULL)
444         {
445                 fprintf(stderr, _("%s: could not open file \"%s\" for reading: %s\n"),
446                                 progname, path, strerror(errno));
447                 exit_nicely();
448         }
449
450         /* pass over the file twice - the first time to size the result */
451
452         while ((c = fgetc(infile)) != EOF)
453         {
454                 linelen++;
455                 if (c == '\n')
456                 {
457                         nlines++;
458                         if (linelen > maxlength)
459                                 maxlength = linelen;
460                         linelen = 0;
461                 }
462         }
463
464         /* handle last line without a terminating newline (yuck) */
465         if (linelen)
466                 nlines++;
467         if (linelen > maxlength)
468                 maxlength = linelen;
469
470         /* set up the result and the line buffer */
471         result = (char **) pg_malloc((nlines + 1) * sizeof(char *));
472         buffer = (char *) pg_malloc(maxlength + 1);
473
474         /* now reprocess the file and store the lines */
475         rewind(infile);
476         n = 0;
477         while (fgets(buffer, maxlength + 1, infile) != NULL && n < nlines)
478                 result[n++] = pg_strdup(buffer);
479
480         fclose(infile);
481         free(buffer);
482         result[n] = NULL;
483
484         return result;
485 }
486
487 /*
488  * write an array of lines to a file
489  *
490  * This is only used to write text files.  Use fopen "w" not PG_BINARY_W
491  * so that the resulting configuration files are nicely editable on Windows.
492  */
493 static void
494 writefile(char *path, char **lines)
495 {
496         FILE       *out_file;
497         char      **line;
498
499         if ((out_file = fopen(path, "w")) == NULL)
500         {
501                 fprintf(stderr, _("%s: could not open file \"%s\" for writing: %s\n"),
502                                 progname, path, strerror(errno));
503                 exit_nicely();
504         }
505         for (line = lines; *line != NULL; line++)
506         {
507                 if (fputs(*line, out_file) < 0)
508                 {
509                         fprintf(stderr, _("%s: could not write file \"%s\": %s\n"),
510                                         progname, path, strerror(errno));
511                         exit_nicely();
512                 }
513                 free(*line);
514         }
515         if (fclose(out_file))
516         {
517                 fprintf(stderr, _("%s: could not write file \"%s\": %s\n"),
518                                 progname, path, strerror(errno));
519                 exit_nicely();
520         }
521 }
522
523 /*
524  * walkdir: recursively walk a directory, applying the action to each
525  * regular file and directory (including the named directory itself).
526  *
527  * Adapted from copydir() in copydir.c.
528  */
529 static void
530 walkdir(char *path, void (*action) (char *fname, bool isdir))
531 {
532         DIR                *dir;
533         struct dirent *direntry;
534         char            subpath[MAXPGPATH];
535
536         dir = opendir(path);
537         if (dir == NULL)
538         {
539                 fprintf(stderr, _("%s: could not open directory \"%s\": %s\n"),
540                                 progname, path, strerror(errno));
541                 exit_nicely();
542         }
543
544         while (errno = 0, (direntry = readdir(dir)) != NULL)
545         {
546                 struct stat fst;
547
548                 if (strcmp(direntry->d_name, ".") == 0 ||
549                         strcmp(direntry->d_name, "..") == 0)
550                         continue;
551
552                 snprintf(subpath, MAXPGPATH, "%s/%s", path, direntry->d_name);
553
554                 if (lstat(subpath, &fst) < 0)
555                 {
556                         fprintf(stderr, _("%s: could not stat file \"%s\": %s\n"),
557                                         progname, subpath, strerror(errno));
558                         exit_nicely();
559                 }
560
561                 if (S_ISDIR(fst.st_mode))
562                         walkdir(subpath, action);
563                 else if (S_ISREG(fst.st_mode))
564                         (*action) (subpath, false);
565         }
566
567 #ifdef WIN32
568         /*
569          * This fix is in mingw cvs (runtime/mingwex/dirent.c rev 1.4), but not in
570          * released version
571          */
572         if (GetLastError() == ERROR_NO_MORE_FILES)
573                 errno = 0;
574 #endif
575
576         if (errno)
577         {
578                 fprintf(stderr, _("%s: could not read directory \"%s\": %s\n"),
579                                 progname, path, strerror(errno));
580                 exit_nicely();
581         }
582
583         closedir(dir);
584
585         /*
586          * It's important to fsync the destination directory itself as individual
587          * file fsyncs don't guarantee that the directory entry for the file is
588          * synced.      Recent versions of ext4 have made the window much wider but
589          * it's been an issue for ext3 and other filesystems in the past.
590          */
591         (*action) (path, true);
592 }
593
594 /*
595  * Hint to the OS that it should get ready to fsync() this file.
596  */
597 static void
598 pre_sync_fname(char *fname, bool isdir)
599 {
600 #if defined(HAVE_SYNC_FILE_RANGE) || \
601         (defined(USE_POSIX_FADVISE) && defined(POSIX_FADV_DONTNEED))
602         int                     fd;
603
604         fd = open(fname, O_RDONLY | PG_BINARY);
605
606         /*
607          * Some OSs don't allow us to open directories at all (Windows returns
608          * EACCES)
609          */
610         if (fd < 0 && isdir && (errno == EISDIR || errno == EACCES))
611                 return;
612
613         if (fd < 0)
614         {
615                 fprintf(stderr, _("%s: could not open file \"%s\": %s\n"),
616                                 progname, fname, strerror(errno));
617                 exit_nicely();
618         }
619
620         /*
621          * Prefer sync_file_range, else use posix_fadvise.      We ignore any error
622          * here since this operation is only a hint anyway.
623          */
624 #if defined(HAVE_SYNC_FILE_RANGE)
625         sync_file_range(fd, 0, 0, SYNC_FILE_RANGE_WRITE);
626 #elif defined(USE_POSIX_FADVISE) && defined(POSIX_FADV_DONTNEED)
627         posix_fadvise(fd, 0, 0, POSIX_FADV_DONTNEED);
628 #endif
629
630         close(fd);
631 #endif
632 }
633
634 /*
635  * fsync a file or directory
636  *
637  * Try to fsync directories but ignore errors that indicate the OS
638  * just doesn't allow/require fsyncing directories.
639  *
640  * Adapted from fsync_fname() in copydir.c.
641  */
642 static void
643 fsync_fname(char *fname, bool isdir)
644 {
645         int                     fd;
646         int                     returncode;
647
648         /*
649          * Some OSs require directories to be opened read-only whereas other
650          * systems don't allow us to fsync files opened read-only; so we need both
651          * cases here
652          */
653         if (!isdir)
654                 fd = open(fname, O_RDWR | PG_BINARY);
655         else
656                 fd = open(fname, O_RDONLY | PG_BINARY);
657
658         /*
659          * Some OSs don't allow us to open directories at all (Windows returns
660          * EACCES)
661          */
662         if (fd < 0 && isdir && (errno == EISDIR || errno == EACCES))
663                 return;
664
665         else if (fd < 0)
666         {
667                 fprintf(stderr, _("%s: could not open file \"%s\": %s\n"),
668                                 progname, fname, strerror(errno));
669                 exit_nicely();
670         }
671
672         returncode = fsync(fd);
673
674         /* Some OSs don't allow us to fsync directories at all */
675         if (returncode != 0 && isdir && errno == EBADF)
676         {
677                 close(fd);
678                 return;
679         }
680
681         if (returncode != 0)
682         {
683                 fprintf(stderr, _("%s: could not fsync file \"%s\": %s\n"),
684                                 progname, fname, strerror(errno));
685                 exit_nicely();
686         }
687
688         close(fd);
689 }
690
691 /*
692  * Open a subcommand with suitable error messaging
693  */
694 static FILE *
695 popen_check(const char *command, const char *mode)
696 {
697         FILE       *cmdfd;
698
699         fflush(stdout);
700         fflush(stderr);
701         errno = 0;
702         cmdfd = popen(command, mode);
703         if (cmdfd == NULL)
704                 fprintf(stderr, _("%s: could not execute command \"%s\": %s\n"),
705                                 progname, command, strerror(errno));
706         return cmdfd;
707 }
708
709 /*
710  * clean up any files we created on failure
711  * if we created the data directory remove it too
712  */
713 static void
714 exit_nicely(void)
715 {
716         if (!noclean)
717         {
718                 if (made_new_pgdata)
719                 {
720                         fprintf(stderr, _("%s: removing data directory \"%s\"\n"),
721                                         progname, pg_data);
722                         if (!rmtree(pg_data, true))
723                                 fprintf(stderr, _("%s: failed to remove data directory\n"),
724                                                 progname);
725                 }
726                 else if (found_existing_pgdata)
727                 {
728                         fprintf(stderr,
729                                         _("%s: removing contents of data directory \"%s\"\n"),
730                                         progname, pg_data);
731                         if (!rmtree(pg_data, false))
732                                 fprintf(stderr, _("%s: failed to remove contents of data directory\n"),
733                                                 progname);
734                 }
735
736                 if (made_new_xlogdir)
737                 {
738                         fprintf(stderr, _("%s: removing transaction log directory \"%s\"\n"),
739                                         progname, xlog_dir);
740                         if (!rmtree(xlog_dir, true))
741                                 fprintf(stderr, _("%s: failed to remove transaction log directory\n"),
742                                                 progname);
743                 }
744                 else if (found_existing_xlogdir)
745                 {
746                         fprintf(stderr,
747                         _("%s: removing contents of transaction log directory \"%s\"\n"),
748                                         progname, xlog_dir);
749                         if (!rmtree(xlog_dir, false))
750                                 fprintf(stderr, _("%s: failed to remove contents of transaction log directory\n"),
751                                                 progname);
752                 }
753                 /* otherwise died during startup, do nothing! */
754         }
755         else
756         {
757                 if (made_new_pgdata || found_existing_pgdata)
758                         fprintf(stderr,
759                           _("%s: data directory \"%s\" not removed at user's request\n"),
760                                         progname, pg_data);
761
762                 if (made_new_xlogdir || found_existing_xlogdir)
763                         fprintf(stderr,
764                                         _("%s: transaction log directory \"%s\" not removed at user's request\n"),
765                                         progname, xlog_dir);
766         }
767
768         exit(1);
769 }
770
771 /*
772  * find the current user
773  *
774  * on unix make sure it isn't root
775  */
776 static char *
777 get_id(void)
778 {
779         const char         *username;
780
781 #ifndef WIN32
782         if (geteuid() == 0)                     /* 0 is root's uid */
783         {
784                 fprintf(stderr,
785                                 _("%s: cannot be run as root\n"
786                                   "Please log in (using, e.g., \"su\") as the "
787                                   "(unprivileged) user that will\n"
788                                   "own the server process.\n"),
789                                 progname);
790                 exit(1);
791         }
792 #endif
793
794         username = get_user_name_or_exit(progname);
795
796         return pg_strdup(username);
797 }
798
799 static char *
800 encodingid_to_string(int enc)
801 {
802         char            result[20];
803
804         sprintf(result, "%d", enc);
805         return pg_strdup(result);
806 }
807
808 /*
809  * get the encoding id for a given encoding name
810  */
811 static char *
812 get_encoding_id(char *encoding_name)
813 {
814         int                     enc;
815
816         if (encoding_name && *encoding_name)
817         {
818                 if ((enc = pg_valid_server_encoding(encoding_name)) >= 0)
819                         return encodingid_to_string(enc);
820         }
821         fprintf(stderr, _("%s: \"%s\" is not a valid server encoding name\n"),
822                         progname, encoding_name ? encoding_name : "(null)");
823         exit(1);
824 }
825
826 /*
827  * Support for determining the best default text search configuration.
828  * We key this off the first part of LC_CTYPE (ie, the language name).
829  */
830 struct tsearch_config_match
831 {
832         const char *tsconfname;
833         const char *langname;
834 };
835
836 static const struct tsearch_config_match tsearch_config_languages[] =
837 {
838         {"danish", "da"},
839         {"danish", "Danish"},
840         {"dutch", "nl"},
841         {"dutch", "Dutch"},
842         {"english", "C"},
843         {"english", "POSIX"},
844         {"english", "en"},
845         {"english", "English"},
846         {"finnish", "fi"},
847         {"finnish", "Finnish"},
848         {"french", "fr"},
849         {"french", "French"},
850         {"german", "de"},
851         {"german", "German"},
852         {"hungarian", "hu"},
853         {"hungarian", "Hungarian"},
854         {"italian", "it"},
855         {"italian", "Italian"},
856         {"norwegian", "no"},
857         {"norwegian", "Norwegian"},
858         {"portuguese", "pt"},
859         {"portuguese", "Portuguese"},
860         {"romanian", "ro"},
861         {"russian", "ru"},
862         {"russian", "Russian"},
863         {"spanish", "es"},
864         {"spanish", "Spanish"},
865         {"swedish", "sv"},
866         {"swedish", "Swedish"},
867         {"turkish", "tr"},
868         {"turkish", "Turkish"},
869         {NULL, NULL}                            /* end marker */
870 };
871
872 /*
873  * Look for a text search configuration matching lc_ctype, and return its
874  * name; return NULL if no match.
875  */
876 static const char *
877 find_matching_ts_config(const char *lc_type)
878 {
879         int                     i;
880         char       *langname,
881                            *ptr;
882
883         /*
884          * Convert lc_ctype to a language name by stripping everything after an
885          * underscore (usual case) or a hyphen (Windows "locale name"; see
886          * comments at IsoLocaleName()).
887          *
888          * XXX Should ' ' be a stop character?  This would select "norwegian" for
889          * the Windows locale "Norwegian (Nynorsk)_Norway.1252".  If we do so, we
890          * should also accept the "nn" and "nb" Unix locales.
891          *
892          * Just for paranoia, we also stop at '.' or '@'.
893          */
894         if (lc_type == NULL)
895                 langname = pg_strdup("");
896         else
897         {
898                 ptr = langname = pg_strdup(lc_type);
899                 while (*ptr &&
900                            *ptr != '_' && *ptr != '-' && *ptr != '.' && *ptr != '@')
901                         ptr++;
902                 *ptr = '\0';
903         }
904
905         for (i = 0; tsearch_config_languages[i].tsconfname; i++)
906         {
907                 if (pg_strcasecmp(tsearch_config_languages[i].langname, langname) == 0)
908                 {
909                         free(langname);
910                         return tsearch_config_languages[i].tsconfname;
911                 }
912         }
913
914         free(langname);
915         return NULL;
916 }
917
918
919 /*
920  * make the data directory (or one of its subdirectories if subdir is not NULL)
921  */
922 static bool
923 mkdatadir(const char *subdir)
924 {
925         char       *path;
926
927         if (subdir)
928                 path = psprintf("%s/%s", pg_data, subdir);
929         else
930                 path = pg_strdup(pg_data);
931
932         if (pg_mkdir_p(path, S_IRWXU) == 0)
933                 return true;
934
935         fprintf(stderr, _("%s: could not create directory \"%s\": %s\n"),
936                         progname, path, strerror(errno));
937
938         return false;
939 }
940
941
942 /*
943  * set name of given input file variable under data directory
944  */
945 static void
946 set_input(char **dest, char *filename)
947 {
948         *dest = psprintf("%s/%s", share_path, filename);
949 }
950
951 /*
952  * check that given input file exists
953  */
954 static void
955 check_input(char *path)
956 {
957         struct stat statbuf;
958
959         if (stat(path, &statbuf) != 0)
960         {
961                 if (errno == ENOENT)
962                 {
963                         fprintf(stderr,
964                                         _("%s: file \"%s\" does not exist\n"), progname, path);
965                         fprintf(stderr,
966                                         _("This might mean you have a corrupted installation or identified\n"
967                                         "the wrong directory with the invocation option -L.\n"));
968                 }
969                 else
970                 {
971                         fprintf(stderr,
972                                  _("%s: could not access file \"%s\": %s\n"), progname, path,
973                                         strerror(errno));
974                         fprintf(stderr,
975                                         _("This might mean you have a corrupted installation or identified\n"
976                                         "the wrong directory with the invocation option -L.\n"));
977                 }
978                 exit(1);
979         }
980         if (!S_ISREG(statbuf.st_mode))
981         {
982                 fprintf(stderr,
983                                 _("%s: file \"%s\" is not a regular file\n"), progname, path);
984                 fprintf(stderr,
985                 _("This might mean you have a corrupted installation or identified\n"
986                   "the wrong directory with the invocation option -L.\n"));
987                 exit(1);
988         }
989 }
990
991 /*
992  * write out the PG_VERSION file in the data dir, or its subdirectory
993  * if extrapath is not NULL
994  */
995 static void
996 write_version_file(char *extrapath)
997 {
998         FILE       *version_file;
999         char       *path;
1000
1001         if (extrapath == NULL)
1002                 path = psprintf("%s/PG_VERSION", pg_data);
1003         else
1004                 path = psprintf("%s/%s/PG_VERSION", pg_data, extrapath);
1005
1006         if ((version_file = fopen(path, PG_BINARY_W)) == NULL)
1007         {
1008                 fprintf(stderr, _("%s: could not open file \"%s\" for writing: %s\n"),
1009                                 progname, path, strerror(errno));
1010                 exit_nicely();
1011         }
1012         if (fprintf(version_file, "%s\n", PG_MAJORVERSION) < 0 ||
1013                 fclose(version_file))
1014         {
1015                 fprintf(stderr, _("%s: could not write file \"%s\": %s\n"),
1016                                 progname, path, strerror(errno));
1017                 exit_nicely();
1018         }
1019         free(path);
1020 }
1021
1022 /*
1023  * set up an empty config file so we can check config settings by launching
1024  * a test backend
1025  */
1026 static void
1027 set_null_conf(void)
1028 {
1029         FILE       *conf_file;
1030         char       *path;
1031
1032         path = psprintf("%s/postgresql.conf", pg_data);
1033         conf_file = fopen(path, PG_BINARY_W);
1034         if (conf_file == NULL)
1035         {
1036                 fprintf(stderr, _("%s: could not open file \"%s\" for writing: %s\n"),
1037                                 progname, path, strerror(errno));
1038                 exit_nicely();
1039         }
1040         if (fclose(conf_file))
1041         {
1042                 fprintf(stderr, _("%s: could not write file \"%s\": %s\n"),
1043                                 progname, path, strerror(errno));
1044                 exit_nicely();
1045         }
1046         free(path);
1047 }
1048
1049 /*
1050  * Determine which dynamic shared memory implementation should be used on
1051  * this platform.  POSIX shared memory is preferable because the default
1052  * allocation limits are much higher than the limits for System V on most
1053  * systems that support both, but the fact that a platform has shm_open
1054  * doesn't guarantee that that call will succeed when attempted.  So, we
1055  * attempt to reproduce what the postmaster will do when allocating a POSIX
1056  * segment in dsm_impl.c; if it doesn't work, we assume it won't work for
1057  * the postmaster either, and configure the cluster for System V shared
1058  * memory instead.
1059  */
1060 static char *
1061 choose_dsm_implementation(void)
1062 {
1063 #ifdef HAVE_SHM_OPEN
1064         int             ntries = 10;
1065
1066         while (ntries > 0)
1067         {
1068                 uint32  handle;
1069                 char    name[64];
1070                 int             fd;
1071
1072                 handle = random();
1073                 snprintf(name, 64, "/PostgreSQL.%u", handle);
1074                 if ((fd = shm_open(name, O_CREAT | O_RDWR | O_EXCL, 0600)) != -1)
1075                 {
1076                         close(fd);
1077                         shm_unlink(name);
1078                         return "posix";
1079                 }
1080                 if (errno != EEXIST)
1081                         break;
1082                 --ntries;
1083         }
1084 #endif
1085
1086 #ifdef WIN32
1087         return "windows";
1088 #else
1089         return "sysv";
1090 #endif
1091 }
1092
1093 /*
1094  * Determine platform-specific config settings
1095  *
1096  * Use reasonable values if kernel will let us, else scale back.  Probe
1097  * for max_connections first since it is subject to more constraints than
1098  * shared_buffers.
1099  */
1100 static void
1101 test_config_settings(void)
1102 {
1103         /*
1104          * This macro defines the minimum shared_buffers we want for a given
1105          * max_connections value. The arrays show the settings to try.
1106          */
1107 #define MIN_BUFS_FOR_CONNS(nconns)      ((nconns) * 10)
1108
1109         static const int trial_conns[] = {
1110                 100, 50, 40, 30, 20, 10
1111         };
1112         static const int trial_bufs[] = {
1113                 16384, 8192, 4096, 3584, 3072, 2560, 2048, 1536,
1114                 1000, 900, 800, 700, 600, 500,
1115                 400, 300, 200, 100, 50
1116         };
1117
1118         char            cmd[MAXPGPATH];
1119         const int       connslen = sizeof(trial_conns) / sizeof(int);
1120         const int       bufslen = sizeof(trial_bufs) / sizeof(int);
1121         int                     i,
1122                                 status,
1123                                 test_conns,
1124                                 test_buffs,
1125                                 ok_buffers = 0;
1126
1127
1128         printf(_("selecting default max_connections ... "));
1129         fflush(stdout);
1130
1131         for (i = 0; i < connslen; i++)
1132         {
1133                 test_conns = trial_conns[i];
1134                 test_buffs = MIN_BUFS_FOR_CONNS(test_conns);
1135
1136                 snprintf(cmd, sizeof(cmd),
1137                                  SYSTEMQUOTE "\"%s\" --boot -x0 %s "
1138                                  "-c max_connections=%d "
1139                                  "-c shared_buffers=%d "
1140                                  "-c dynamic_shared_memory_type=none "
1141                                  "< \"%s\" > \"%s\" 2>&1" SYSTEMQUOTE,
1142                                  backend_exec, boot_options,
1143                                  test_conns, test_buffs,
1144                                  DEVNULL, DEVNULL);
1145                 status = system(cmd);
1146                 if (status == 0)
1147                 {
1148                         ok_buffers = test_buffs;
1149                         break;
1150                 }
1151         }
1152         if (i >= connslen)
1153                 i = connslen - 1;
1154         n_connections = trial_conns[i];
1155
1156         printf("%d\n", n_connections);
1157
1158         printf(_("selecting default shared_buffers ... "));
1159         fflush(stdout);
1160
1161         for (i = 0; i < bufslen; i++)
1162         {
1163                 /* Use same amount of memory, independent of BLCKSZ */
1164                 test_buffs = (trial_bufs[i] * 8192) / BLCKSZ;
1165                 if (test_buffs <= ok_buffers)
1166                 {
1167                         test_buffs = ok_buffers;
1168                         break;
1169                 }
1170
1171                 snprintf(cmd, sizeof(cmd),
1172                                  SYSTEMQUOTE "\"%s\" --boot -x0 %s "
1173                                  "-c max_connections=%d "
1174                                  "-c shared_buffers=%d "
1175                                  "-c dynamic_shared_memory_type=none "
1176                                  "< \"%s\" > \"%s\" 2>&1" SYSTEMQUOTE,
1177                                  backend_exec, boot_options,
1178                                  n_connections, test_buffs,
1179                                  DEVNULL, DEVNULL);
1180                 status = system(cmd);
1181                 if (status == 0)
1182                         break;
1183         }
1184         n_buffers = test_buffs;
1185
1186         if ((n_buffers * (BLCKSZ / 1024)) % 1024 == 0)
1187                 printf("%dMB\n", (n_buffers * (BLCKSZ / 1024)) / 1024);
1188         else
1189                 printf("%dkB\n", n_buffers * (BLCKSZ / 1024));
1190
1191         printf(_("selecting dynamic shared memory implementation ... "));
1192         fflush(stdout);
1193         dynamic_shared_memory_type = choose_dsm_implementation();
1194         printf("%s\n", dynamic_shared_memory_type);
1195 }
1196
1197 /*
1198  * set up all the config files
1199  */
1200 static void
1201 setup_config(void)
1202 {
1203         char      **conflines;
1204         char            repltok[MAXPGPATH];
1205         char            path[MAXPGPATH];
1206         const char *default_timezone;
1207         char       *autoconflines[3];
1208
1209         fputs(_("creating configuration files ... "), stdout);
1210         fflush(stdout);
1211
1212         /* postgresql.conf */
1213
1214         conflines = readfile(conf_file);
1215
1216         snprintf(repltok, sizeof(repltok), "max_connections = %d", n_connections);
1217         conflines = replace_token(conflines, "#max_connections = 100", repltok);
1218
1219         if ((n_buffers * (BLCKSZ / 1024)) % 1024 == 0)
1220                 snprintf(repltok, sizeof(repltok), "shared_buffers = %dMB",
1221                                  (n_buffers * (BLCKSZ / 1024)) / 1024);
1222         else
1223                 snprintf(repltok, sizeof(repltok), "shared_buffers = %dkB",
1224                                  n_buffers * (BLCKSZ / 1024));
1225         conflines = replace_token(conflines, "#shared_buffers = 32MB", repltok);
1226
1227 #ifdef HAVE_UNIX_SOCKETS
1228         snprintf(repltok, sizeof(repltok), "#unix_socket_directories = '%s'",
1229                          DEFAULT_PGSOCKET_DIR);
1230 #else
1231         snprintf(repltok, sizeof(repltok), "#unix_socket_directories = ''");
1232 #endif
1233         conflines = replace_token(conflines, "#unix_socket_directories = '/tmp'",
1234                                                           repltok);
1235
1236 #if DEF_PGPORT != 5432
1237         snprintf(repltok, sizeof(repltok), "#port = %d", DEF_PGPORT);
1238         conflines = replace_token(conflines, "#port = 5432", repltok);
1239 #endif
1240
1241         snprintf(repltok, sizeof(repltok), "lc_messages = '%s'",
1242                          escape_quotes(lc_messages));
1243         conflines = replace_token(conflines, "#lc_messages = 'C'", repltok);
1244
1245         snprintf(repltok, sizeof(repltok), "lc_monetary = '%s'",
1246                          escape_quotes(lc_monetary));
1247         conflines = replace_token(conflines, "#lc_monetary = 'C'", repltok);
1248
1249         snprintf(repltok, sizeof(repltok), "lc_numeric = '%s'",
1250                          escape_quotes(lc_numeric));
1251         conflines = replace_token(conflines, "#lc_numeric = 'C'", repltok);
1252
1253         snprintf(repltok, sizeof(repltok), "lc_time = '%s'",
1254                          escape_quotes(lc_time));
1255         conflines = replace_token(conflines, "#lc_time = 'C'", repltok);
1256
1257         switch (locale_date_order(lc_time))
1258         {
1259                 case DATEORDER_YMD:
1260                         strcpy(repltok, "datestyle = 'iso, ymd'");
1261                         break;
1262                 case DATEORDER_DMY:
1263                         strcpy(repltok, "datestyle = 'iso, dmy'");
1264                         break;
1265                 case DATEORDER_MDY:
1266                 default:
1267                         strcpy(repltok, "datestyle = 'iso, mdy'");
1268                         break;
1269         }
1270         conflines = replace_token(conflines, "#datestyle = 'iso, mdy'", repltok);
1271
1272         snprintf(repltok, sizeof(repltok),
1273                          "default_text_search_config = 'pg_catalog.%s'",
1274                          escape_quotes(default_text_search_config));
1275         conflines = replace_token(conflines,
1276                                                  "#default_text_search_config = 'pg_catalog.simple'",
1277                                                           repltok);
1278
1279         default_timezone = select_default_timezone(share_path);
1280         if (default_timezone)
1281         {
1282                 snprintf(repltok, sizeof(repltok), "timezone = '%s'",
1283                                  escape_quotes(default_timezone));
1284                 conflines = replace_token(conflines, "#timezone = 'GMT'", repltok);
1285                 snprintf(repltok, sizeof(repltok), "log_timezone = '%s'",
1286                                  escape_quotes(default_timezone));
1287                 conflines = replace_token(conflines, "#log_timezone = 'GMT'", repltok);
1288         }
1289
1290         snprintf(repltok, sizeof(repltok), "dynamic_shared_memory_type = %s",
1291                          dynamic_shared_memory_type);
1292         conflines = replace_token(conflines, "#dynamic_shared_memory_type = posix",
1293                                                           repltok);
1294
1295         snprintf(path, sizeof(path), "%s/postgresql.conf", pg_data);
1296
1297         writefile(path, conflines);
1298         if (chmod(path, S_IRUSR | S_IWUSR) != 0)
1299         {
1300                 fprintf(stderr, _("%s: could not change permissions of \"%s\": %s\n"),
1301                                 progname, path, strerror(errno));
1302                 exit_nicely();
1303         }
1304
1305         /*
1306          * create the automatic configuration file to store the configuration
1307          * parameters set by ALTER SYSTEM command. The parameters present in this
1308          * file will override the value of parameters that exists before parse of
1309          * this file.
1310          */
1311         autoconflines[0] = pg_strdup("# Do not edit this file manually!\n");
1312         autoconflines[1] = pg_strdup("# It will be overwritten by the ALTER SYSTEM command.\n");
1313         autoconflines[2] = NULL;
1314
1315         sprintf(path, "%s/%s", pg_data, PG_AUTOCONF_FILENAME);
1316
1317         writefile(path, autoconflines);
1318         if (chmod(path, S_IRUSR | S_IWUSR) != 0)
1319         {
1320                 fprintf(stderr, _("%s: could not change permissions of \"%s\": %s\n"),
1321                                 progname, path, strerror(errno));
1322                 exit_nicely();
1323         }
1324
1325         free(conflines);
1326
1327
1328         /* pg_hba.conf */
1329
1330         conflines = readfile(hba_file);
1331
1332 #ifndef HAVE_UNIX_SOCKETS
1333         conflines = filter_lines_with_token(conflines, "@remove-line-for-nolocal@");
1334 #else
1335         conflines = replace_token(conflines, "@remove-line-for-nolocal@", "");
1336 #endif
1337
1338 #ifdef HAVE_IPV6
1339
1340         /*
1341          * Probe to see if there is really any platform support for IPv6, and
1342          * comment out the relevant pg_hba line if not.  This avoids runtime
1343          * warnings if getaddrinfo doesn't actually cope with IPv6.  Particularly
1344          * useful on Windows, where executables built on a machine with IPv6 may
1345          * have to run on a machine without.
1346          */
1347         {
1348                 struct addrinfo *gai_result;
1349                 struct addrinfo hints;
1350                 int                     err = 0;
1351
1352 #ifdef WIN32
1353                 /* need to call WSAStartup before calling getaddrinfo */
1354                 WSADATA         wsaData;
1355
1356                 err = WSAStartup(MAKEWORD(2, 2), &wsaData);
1357 #endif
1358
1359                 /* for best results, this code should match parse_hba() */
1360                 hints.ai_flags = AI_NUMERICHOST;
1361                 hints.ai_family = PF_UNSPEC;
1362                 hints.ai_socktype = 0;
1363                 hints.ai_protocol = 0;
1364                 hints.ai_addrlen = 0;
1365                 hints.ai_canonname = NULL;
1366                 hints.ai_addr = NULL;
1367                 hints.ai_next = NULL;
1368
1369                 if (err != 0 ||
1370                         getaddrinfo("::1", NULL, &hints, &gai_result) != 0)
1371                         conflines = replace_token(conflines,
1372                                                            "host    all             all             ::1",
1373                                                          "#host    all             all             ::1");
1374         }
1375 #else                                                   /* !HAVE_IPV6 */
1376         /* If we didn't compile IPV6 support at all, always comment it out */
1377         conflines = replace_token(conflines,
1378                                                           "host    all             all             ::1",
1379                                                           "#host    all             all             ::1");
1380 #endif   /* HAVE_IPV6 */
1381
1382         /* Replace default authentication methods */
1383         conflines = replace_token(conflines,
1384                                                           "@authmethodhost@",
1385                                                           authmethodhost);
1386         conflines = replace_token(conflines,
1387                                                           "@authmethodlocal@",
1388                                                           authmethodlocal);
1389
1390         conflines = replace_token(conflines,
1391                                                           "@authcomment@",
1392                                                           (strcmp(authmethodlocal, "trust") == 0 || strcmp(authmethodhost, "trust") == 0) ? AUTHTRUST_WARNING : "");
1393
1394         /* Replace username for replication */
1395         conflines = replace_token(conflines,
1396                                                           "@default_username@",
1397                                                           username);
1398
1399         snprintf(path, sizeof(path), "%s/pg_hba.conf", pg_data);
1400
1401         writefile(path, conflines);
1402         if (chmod(path, S_IRUSR | S_IWUSR) != 0)
1403         {
1404                 fprintf(stderr, _("%s: could not change permissions of \"%s\": %s\n"),
1405                                 progname, path, strerror(errno));
1406                 exit_nicely();
1407         }
1408
1409         free(conflines);
1410
1411         /* pg_ident.conf */
1412
1413         conflines = readfile(ident_file);
1414
1415         snprintf(path, sizeof(path), "%s/pg_ident.conf", pg_data);
1416
1417         writefile(path, conflines);
1418         if (chmod(path, S_IRUSR | S_IWUSR) != 0)
1419         {
1420                 fprintf(stderr, _("%s: could not change permissions of \"%s\": %s\n"),
1421                                 progname, path, strerror(errno));
1422                 exit_nicely();
1423         }
1424
1425         free(conflines);
1426
1427         check_ok();
1428 }
1429
1430
1431 /*
1432  * run the BKI script in bootstrap mode to create template1
1433  */
1434 static void
1435 bootstrap_template1(void)
1436 {
1437         PG_CMD_DECL;
1438         char      **line;
1439         char       *talkargs = "";
1440         char      **bki_lines;
1441         char            headerline[MAXPGPATH];
1442         char            buf[64];
1443
1444         printf(_("creating template1 database in %s/base/1 ... "), pg_data);
1445         fflush(stdout);
1446
1447         if (debug)
1448                 talkargs = "-d 5";
1449
1450         bki_lines = readfile(bki_file);
1451
1452         /* Check that bki file appears to be of the right version */
1453
1454         snprintf(headerline, sizeof(headerline), "# PostgreSQL %s\n",
1455                          PG_MAJORVERSION);
1456
1457         if (strcmp(headerline, *bki_lines) != 0)
1458         {
1459                 fprintf(stderr,
1460                                 _("%s: input file \"%s\" does not belong to PostgreSQL %s\n"
1461                                   "Check your installation or specify the correct path "
1462                                   "using the option -L.\n"),
1463                                 progname, bki_file, PG_VERSION);
1464                 exit_nicely();
1465         }
1466
1467         /* Substitute for various symbols used in the BKI file */
1468
1469         sprintf(buf, "%d", NAMEDATALEN);
1470         bki_lines = replace_token(bki_lines, "NAMEDATALEN", buf);
1471
1472         sprintf(buf, "%d", (int) sizeof(Pointer));
1473         bki_lines = replace_token(bki_lines, "SIZEOF_POINTER", buf);
1474
1475         bki_lines = replace_token(bki_lines, "ALIGNOF_POINTER",
1476                                                           (sizeof(Pointer) == 4) ? "i" : "d");
1477
1478         bki_lines = replace_token(bki_lines, "FLOAT4PASSBYVAL",
1479                                                           FLOAT4PASSBYVAL ? "true" : "false");
1480
1481         bki_lines = replace_token(bki_lines, "FLOAT8PASSBYVAL",
1482                                                           FLOAT8PASSBYVAL ? "true" : "false");
1483
1484         bki_lines = replace_token(bki_lines, "POSTGRES", escape_quotes(username));
1485
1486         bki_lines = replace_token(bki_lines, "ENCODING", encodingid);
1487
1488         bki_lines = replace_token(bki_lines, "LC_COLLATE", escape_quotes(lc_collate));
1489
1490         bki_lines = replace_token(bki_lines, "LC_CTYPE", escape_quotes(lc_ctype));
1491
1492         /*
1493          * Pass correct LC_xxx environment to bootstrap.
1494          *
1495          * The shell script arranged to restore the LC settings afterwards, but
1496          * there doesn't seem to be any compelling reason to do that.
1497          */
1498         snprintf(cmd, sizeof(cmd), "LC_COLLATE=%s", lc_collate);
1499         putenv(pg_strdup(cmd));
1500
1501         snprintf(cmd, sizeof(cmd), "LC_CTYPE=%s", lc_ctype);
1502         putenv(pg_strdup(cmd));
1503
1504         unsetenv("LC_ALL");
1505
1506         /* Also ensure backend isn't confused by this environment var: */
1507         unsetenv("PGCLIENTENCODING");
1508
1509         snprintf(cmd, sizeof(cmd),
1510                          "\"%s\" --boot -x1 %s %s %s",
1511                          backend_exec,
1512                          data_checksums ? "-k" : "",
1513                          boot_options, talkargs);
1514
1515         PG_CMD_OPEN;
1516
1517         for (line = bki_lines; *line != NULL; line++)
1518         {
1519                 PG_CMD_PUTS(*line);
1520                 free(*line);
1521         }
1522
1523         PG_CMD_CLOSE;
1524
1525         free(bki_lines);
1526
1527         check_ok();
1528 }
1529
1530 /*
1531  * set up the shadow password table
1532  */
1533 static void
1534 setup_auth(void)
1535 {
1536         PG_CMD_DECL;
1537         const char **line;
1538         static const char *pg_authid_setup[] = {
1539                 /*
1540                  * The authid table shouldn't be readable except through views, to
1541                  * ensure passwords are not publicly visible.
1542                  */
1543                 "REVOKE ALL on pg_authid FROM public;\n",
1544                 NULL
1545         };
1546
1547         fputs(_("initializing pg_authid ... "), stdout);
1548         fflush(stdout);
1549
1550         snprintf(cmd, sizeof(cmd),
1551                          "\"%s\" %s template1 >%s",
1552                          backend_exec, backend_options,
1553                          DEVNULL);
1554
1555         PG_CMD_OPEN;
1556
1557         for (line = pg_authid_setup; *line != NULL; line++)
1558                 PG_CMD_PUTS(*line);
1559
1560         PG_CMD_CLOSE;
1561
1562         check_ok();
1563 }
1564
1565 /*
1566  * get the superuser password if required, and call postgres to set it
1567  */
1568 static void
1569 get_set_pwd(void)
1570 {
1571         PG_CMD_DECL;
1572
1573         char       *pwd1,
1574                            *pwd2;
1575
1576         if (pwprompt)
1577         {
1578                 /*
1579                  * Read password from terminal
1580                  */
1581                 pwd1 = simple_prompt("Enter new superuser password: ", 100, false);
1582                 pwd2 = simple_prompt("Enter it again: ", 100, false);
1583                 if (strcmp(pwd1, pwd2) != 0)
1584                 {
1585                         fprintf(stderr, _("Passwords didn't match.\n"));
1586                         exit_nicely();
1587                 }
1588                 free(pwd2);
1589         }
1590         else
1591         {
1592                 /*
1593                  * Read password from file
1594                  *
1595                  * Ideally this should insist that the file not be world-readable.
1596                  * However, this option is mainly intended for use on Windows where
1597                  * file permissions may not exist at all, so we'll skip the paranoia
1598                  * for now.
1599                  */
1600                 FILE       *pwf = fopen(pwfilename, "r");
1601                 char            pwdbuf[MAXPGPATH];
1602                 int                     i;
1603
1604                 if (!pwf)
1605                 {
1606                         fprintf(stderr, _("%s: could not open file \"%s\" for reading: %s\n"),
1607                                         progname, pwfilename, strerror(errno));
1608                         exit_nicely();
1609                 }
1610                 if (!fgets(pwdbuf, sizeof(pwdbuf), pwf))
1611                 {
1612                         fprintf(stderr, _("%s: could not read password from file \"%s\": %s\n"),
1613                                         progname, pwfilename, strerror(errno));
1614                         exit_nicely();
1615                 }
1616                 fclose(pwf);
1617
1618                 i = strlen(pwdbuf);
1619                 while (i > 0 && (pwdbuf[i - 1] == '\r' || pwdbuf[i - 1] == '\n'))
1620                         pwdbuf[--i] = '\0';
1621
1622                 pwd1 = pg_strdup(pwdbuf);
1623
1624         }
1625         printf(_("setting password ... "));
1626         fflush(stdout);
1627
1628         snprintf(cmd, sizeof(cmd),
1629                          "\"%s\" %s template1 >%s",
1630                          backend_exec, backend_options,
1631                          DEVNULL);
1632
1633         PG_CMD_OPEN;
1634
1635         PG_CMD_PRINTF2("ALTER USER \"%s\" WITH PASSWORD E'%s';\n",
1636                                    username, escape_quotes(pwd1));
1637
1638         /* MM: pwd1 is no longer needed, freeing it */
1639         free(pwd1);
1640
1641         PG_CMD_CLOSE;
1642
1643         check_ok();
1644 }
1645
1646 /*
1647  * set up pg_depend
1648  */
1649 static void
1650 setup_depend(void)
1651 {
1652         PG_CMD_DECL;
1653         const char **line;
1654         static const char *pg_depend_setup[] = {
1655                 /*
1656                  * Make PIN entries in pg_depend for all objects made so far in the
1657                  * tables that the dependency code handles.  This is overkill (the
1658                  * system doesn't really depend on having every last weird datatype,
1659                  * for instance) but generating only the minimum required set of
1660                  * dependencies seems hard.
1661                  *
1662                  * Note that we deliberately do not pin the system views, which
1663                  * haven't been created yet.  Also, no conversions, databases, or
1664                  * tablespaces are pinned.
1665                  *
1666                  * First delete any already-made entries; PINs override all else, and
1667                  * must be the only entries for their objects.
1668                  */
1669                 "DELETE FROM pg_depend;\n",
1670                 "VACUUM pg_depend;\n",
1671                 "DELETE FROM pg_shdepend;\n",
1672                 "VACUUM pg_shdepend;\n",
1673
1674                 "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' "
1675                 " FROM pg_class;\n",
1676                 "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' "
1677                 " FROM pg_proc;\n",
1678                 "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' "
1679                 " FROM pg_type;\n",
1680                 "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' "
1681                 " FROM pg_cast;\n",
1682                 "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' "
1683                 " FROM pg_constraint;\n",
1684                 "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' "
1685                 " FROM pg_attrdef;\n",
1686                 "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' "
1687                 " FROM pg_language;\n",
1688                 "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' "
1689                 " FROM pg_operator;\n",
1690                 "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' "
1691                 " FROM pg_opclass;\n",
1692                 "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' "
1693                 " FROM pg_opfamily;\n",
1694                 "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' "
1695                 " FROM pg_amop;\n",
1696                 "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' "
1697                 " FROM pg_amproc;\n",
1698                 "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' "
1699                 " FROM pg_rewrite;\n",
1700                 "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' "
1701                 " FROM pg_trigger;\n",
1702
1703                 /*
1704                  * restriction here to avoid pinning the public namespace
1705                  */
1706                 "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' "
1707                 " FROM pg_namespace "
1708                 "    WHERE nspname LIKE 'pg%';\n",
1709
1710                 "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' "
1711                 " FROM pg_ts_parser;\n",
1712                 "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' "
1713                 " FROM pg_ts_dict;\n",
1714                 "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' "
1715                 " FROM pg_ts_template;\n",
1716                 "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' "
1717                 " FROM pg_ts_config;\n",
1718                 "INSERT INTO pg_depend SELECT 0,0,0, tableoid,oid,0, 'p' "
1719                 " FROM pg_collation;\n",
1720                 "INSERT INTO pg_shdepend SELECT 0,0,0,0, tableoid,oid, 'p' "
1721                 " FROM pg_authid;\n",
1722                 NULL
1723         };
1724
1725         fputs(_("initializing dependencies ... "), stdout);
1726         fflush(stdout);
1727
1728         snprintf(cmd, sizeof(cmd),
1729                          "\"%s\" %s template1 >%s",
1730                          backend_exec, backend_options,
1731                          DEVNULL);
1732
1733         PG_CMD_OPEN;
1734
1735         for (line = pg_depend_setup; *line != NULL; line++)
1736                 PG_CMD_PUTS(*line);
1737
1738         PG_CMD_CLOSE;
1739
1740         check_ok();
1741 }
1742
1743 /*
1744  * set up system views
1745  */
1746 static void
1747 setup_sysviews(void)
1748 {
1749         PG_CMD_DECL;
1750         char      **line;
1751         char      **sysviews_setup;
1752
1753         fputs(_("creating system views ... "), stdout);
1754         fflush(stdout);
1755
1756         sysviews_setup = readfile(system_views_file);
1757
1758         /*
1759          * We use -j here to avoid backslashing stuff in system_views.sql
1760          */
1761         snprintf(cmd, sizeof(cmd),
1762                          "\"%s\" %s -j template1 >%s",
1763                          backend_exec, backend_options,
1764                          DEVNULL);
1765
1766         PG_CMD_OPEN;
1767
1768         for (line = sysviews_setup; *line != NULL; line++)
1769         {
1770                 PG_CMD_PUTS(*line);
1771                 free(*line);
1772         }
1773
1774         PG_CMD_CLOSE;
1775
1776         free(sysviews_setup);
1777
1778         check_ok();
1779 }
1780
1781 /*
1782  * load description data
1783  */
1784 static void
1785 setup_description(void)
1786 {
1787         PG_CMD_DECL;
1788
1789         fputs(_("loading system objects' descriptions ... "), stdout);
1790         fflush(stdout);
1791
1792         snprintf(cmd, sizeof(cmd),
1793                          "\"%s\" %s template1 >%s",
1794                          backend_exec, backend_options,
1795                          DEVNULL);
1796
1797         PG_CMD_OPEN;
1798
1799         PG_CMD_PUTS("CREATE TEMP TABLE tmp_pg_description ( "
1800                                 "       objoid oid, "
1801                                 "       classname name, "
1802                                 "       objsubid int4, "
1803                                 "       description text) WITHOUT OIDS;\n");
1804
1805         PG_CMD_PRINTF1("COPY tmp_pg_description FROM E'%s';\n",
1806                                    escape_quotes(desc_file));
1807
1808         PG_CMD_PUTS("INSERT INTO pg_description "
1809                                 " SELECT t.objoid, c.oid, t.objsubid, t.description "
1810                                 "  FROM tmp_pg_description t, pg_class c "
1811                                 "    WHERE c.relname = t.classname;\n");
1812
1813         PG_CMD_PUTS("CREATE TEMP TABLE tmp_pg_shdescription ( "
1814                                 " objoid oid, "
1815                                 " classname name, "
1816                                 " description text) WITHOUT OIDS;\n");
1817
1818         PG_CMD_PRINTF1("COPY tmp_pg_shdescription FROM E'%s';\n",
1819                                    escape_quotes(shdesc_file));
1820
1821         PG_CMD_PUTS("INSERT INTO pg_shdescription "
1822                                 " SELECT t.objoid, c.oid, t.description "
1823                                 "  FROM tmp_pg_shdescription t, pg_class c "
1824                                 "   WHERE c.relname = t.classname;\n");
1825
1826         /* Create default descriptions for operator implementation functions */
1827         PG_CMD_PUTS("WITH funcdescs AS ( "
1828                                 "SELECT p.oid as p_oid, oprname, "
1829                           "coalesce(obj_description(o.oid, 'pg_operator'),'') as opdesc "
1830                                 "FROM pg_proc p JOIN pg_operator o ON oprcode = p.oid ) "
1831                                 "INSERT INTO pg_description "
1832                                 "  SELECT p_oid, 'pg_proc'::regclass, 0, "
1833                                 "    'implementation of ' || oprname || ' operator' "
1834                                 "  FROM funcdescs "
1835                                 "  WHERE opdesc NOT LIKE 'deprecated%' AND "
1836                                 "  NOT EXISTS (SELECT 1 FROM pg_description "
1837                   "    WHERE objoid = p_oid AND classoid = 'pg_proc'::regclass);\n");
1838
1839         PG_CMD_CLOSE;
1840
1841         check_ok();
1842 }
1843
1844 #ifdef HAVE_LOCALE_T
1845 /*
1846  * "Normalize" a locale name, stripping off encoding tags such as
1847  * ".utf8" (e.g., "en_US.utf8" -> "en_US", but "br_FR.iso885915@euro"
1848  * -> "br_FR@euro").  Return true if a new, different name was
1849  * generated.
1850  */
1851 static bool
1852 normalize_locale_name(char *new, const char *old)
1853 {
1854         char       *n = new;
1855         const char *o = old;
1856         bool            changed = false;
1857
1858         while (*o)
1859         {
1860                 if (*o == '.')
1861                 {
1862                         /* skip over encoding tag such as ".utf8" or ".UTF-8" */
1863                         o++;
1864                         while ((*o >= 'A' && *o <= 'Z')
1865                                    || (*o >= 'a' && *o <= 'z')
1866                                    || (*o >= '0' && *o <= '9')
1867                                    || (*o == '-'))
1868                                 o++;
1869                         changed = true;
1870                 }
1871                 else
1872                         *n++ = *o++;
1873         }
1874         *n = '\0';
1875
1876         return changed;
1877 }
1878 #endif   /* HAVE_LOCALE_T */
1879
1880 /*
1881  * populate pg_collation
1882  */
1883 static void
1884 setup_collation(void)
1885 {
1886 #if defined(HAVE_LOCALE_T) && !defined(WIN32)
1887         int                     i;
1888         FILE       *locale_a_handle;
1889         char            localebuf[NAMEDATALEN]; /* we assume ASCII so this is fine */
1890         int                     count = 0;
1891
1892         PG_CMD_DECL;
1893 #endif
1894
1895         fputs(_("creating collations ... "), stdout);
1896         fflush(stdout);
1897
1898 #if defined(HAVE_LOCALE_T) && !defined(WIN32)
1899         snprintf(cmd, sizeof(cmd),
1900                          "\"%s\" %s template1 >%s",
1901                          backend_exec, backend_options,
1902                          DEVNULL);
1903
1904         locale_a_handle = popen_check("locale -a", "r");
1905         if (!locale_a_handle)
1906                 return;                                 /* complaint already printed */
1907
1908         PG_CMD_OPEN;
1909
1910         PG_CMD_PUTS("CREATE TEMP TABLE tmp_pg_collation ( "
1911                                 "       collname name, "
1912                                 "       locale name, "
1913                                 "       encoding int) WITHOUT OIDS;\n");
1914
1915         while (fgets(localebuf, sizeof(localebuf), locale_a_handle))
1916         {
1917                 size_t          len;
1918                 int                     enc;
1919                 bool            skip;
1920                 char       *quoted_locale;
1921                 char            alias[NAMEDATALEN];
1922
1923                 len = strlen(localebuf);
1924
1925                 if (len == 0 || localebuf[len - 1] != '\n')
1926                 {
1927                         if (debug)
1928                                 fprintf(stderr, _("%s: locale name too long, skipped: \"%s\"\n"),
1929                                                 progname, localebuf);
1930                         continue;
1931                 }
1932                 localebuf[len - 1] = '\0';
1933
1934                 /*
1935                  * Some systems have locale names that don't consist entirely of ASCII
1936                  * letters (such as "bokm&aring;l" or "fran&ccedil;ais").  This is
1937                  * pretty silly, since we need the locale itself to interpret the
1938                  * non-ASCII characters. We can't do much with those, so we filter
1939                  * them out.
1940                  */
1941                 skip = false;
1942                 for (i = 0; i < len; i++)
1943                 {
1944                         if (IS_HIGHBIT_SET(localebuf[i]))
1945                         {
1946                                 skip = true;
1947                                 break;
1948                         }
1949                 }
1950                 if (skip)
1951                 {
1952                         if (debug)
1953                                 fprintf(stderr, _("%s: locale name has non-ASCII characters, skipped: \"%s\"\n"),
1954                                                 progname, localebuf);
1955                         continue;
1956                 }
1957
1958                 enc = pg_get_encoding_from_locale(localebuf, debug);
1959                 if (enc < 0)
1960                 {
1961                         /* error message printed by pg_get_encoding_from_locale() */
1962                         continue;
1963                 }
1964                 if (!PG_VALID_BE_ENCODING(enc))
1965                         continue;                       /* ignore locales for client-only encodings */
1966                 if (enc == PG_SQL_ASCII)
1967                         continue;                       /* C/POSIX are already in the catalog */
1968
1969                 count++;
1970
1971                 quoted_locale = escape_quotes(localebuf);
1972
1973                 PG_CMD_PRINTF3("INSERT INTO tmp_pg_collation VALUES (E'%s', E'%s', %d);\n",
1974                                            quoted_locale, quoted_locale, enc);
1975
1976                 /*
1977                  * Generate aliases such as "en_US" in addition to "en_US.utf8" for
1978                  * ease of use.  Note that collation names are unique per encoding
1979                  * only, so this doesn't clash with "en_US" for LATIN1, say.
1980                  */
1981                 if (normalize_locale_name(alias, localebuf))
1982                 {
1983                         char   *quoted_alias = escape_quotes(alias);
1984
1985                         PG_CMD_PRINTF3("INSERT INTO tmp_pg_collation VALUES (E'%s', E'%s', %d);\n",
1986                                                    quoted_alias, quoted_locale, enc);
1987                         free(quoted_alias);
1988                 }
1989                 free(quoted_locale);
1990         }
1991
1992         /* Add an SQL-standard name */
1993         PG_CMD_PRINTF1("INSERT INTO tmp_pg_collation VALUES ('ucs_basic', 'C', %d);\n", PG_UTF8);
1994
1995         /*
1996          * When copying collations to the final location, eliminate aliases that
1997          * conflict with an existing locale name for the same encoding.  For
1998          * example, "br_FR.iso88591" is normalized to "br_FR", both for encoding
1999          * LATIN1.      But the unnormalized locale "br_FR" already exists for LATIN1.
2000          * Prefer the alias that matches the OS locale name, else the first locale
2001          * name by sort order (arbitrary choice to be deterministic).
2002          *
2003          * Also, eliminate any aliases that conflict with pg_collation's
2004          * hard-wired entries for "C" etc.
2005          */
2006         PG_CMD_PUTS("INSERT INTO pg_collation (collname, collnamespace, collowner, collencoding, collcollate, collctype) "
2007                                 " SELECT DISTINCT ON (collname, encoding)"
2008                                 "   collname, "
2009                                 "   (SELECT oid FROM pg_namespace WHERE nspname = 'pg_catalog') AS collnamespace, "
2010                                 "   (SELECT relowner FROM pg_class WHERE relname = 'pg_collation') AS collowner, "
2011                                 "   encoding, locale, locale "
2012                                 "  FROM tmp_pg_collation"
2013                                 "  WHERE NOT EXISTS (SELECT 1 FROM pg_collation WHERE collname = tmp_pg_collation.collname)"
2014            "  ORDER BY collname, encoding, (collname = locale) DESC, locale;\n");
2015
2016         pclose(locale_a_handle);
2017         PG_CMD_CLOSE;
2018
2019         check_ok();
2020         if (count == 0 && !debug)
2021         {
2022                 printf(_("No usable system locales were found.\n"));
2023                 printf(_("Use the option \"--debug\" to see details.\n"));
2024         }
2025 #else                                                   /* not HAVE_LOCALE_T && not WIN32 */
2026         printf(_("not supported on this platform\n"));
2027         fflush(stdout);
2028 #endif   /* not HAVE_LOCALE_T  && not WIN32 */
2029 }
2030
2031 /*
2032  * load conversion functions
2033  */
2034 static void
2035 setup_conversion(void)
2036 {
2037         PG_CMD_DECL;
2038         char      **line;
2039         char      **conv_lines;
2040
2041         fputs(_("creating conversions ... "), stdout);
2042         fflush(stdout);
2043
2044         snprintf(cmd, sizeof(cmd),
2045                          "\"%s\" %s template1 >%s",
2046                          backend_exec, backend_options,
2047                          DEVNULL);
2048
2049         PG_CMD_OPEN;
2050
2051         conv_lines = readfile(conversion_file);
2052         for (line = conv_lines; *line != NULL; line++)
2053         {
2054                 if (strstr(*line, "DROP CONVERSION") != *line)
2055                         PG_CMD_PUTS(*line);
2056                 free(*line);
2057         }
2058
2059         free(conv_lines);
2060
2061         PG_CMD_CLOSE;
2062
2063         check_ok();
2064 }
2065
2066 /*
2067  * load extra dictionaries (Snowball stemmers)
2068  */
2069 static void
2070 setup_dictionary(void)
2071 {
2072         PG_CMD_DECL;
2073         char      **line;
2074         char      **conv_lines;
2075
2076         fputs(_("creating dictionaries ... "), stdout);
2077         fflush(stdout);
2078
2079         /*
2080          * We use -j here to avoid backslashing stuff
2081          */
2082         snprintf(cmd, sizeof(cmd),
2083                          "\"%s\" %s -j template1 >%s",
2084                          backend_exec, backend_options,
2085                          DEVNULL);
2086
2087         PG_CMD_OPEN;
2088
2089         conv_lines = readfile(dictionary_file);
2090         for (line = conv_lines; *line != NULL; line++)
2091         {
2092                 PG_CMD_PUTS(*line);
2093                 free(*line);
2094         }
2095
2096         free(conv_lines);
2097
2098         PG_CMD_CLOSE;
2099
2100         check_ok();
2101 }
2102
2103 /*
2104  * Set up privileges
2105  *
2106  * We mark most system catalogs as world-readable.      We don't currently have
2107  * to touch functions, languages, or databases, because their default
2108  * permissions are OK.
2109  *
2110  * Some objects may require different permissions by default, so we
2111  * make sure we don't overwrite privilege sets that have already been
2112  * set (NOT NULL).
2113  */
2114 static void
2115 setup_privileges(void)
2116 {
2117         PG_CMD_DECL;
2118         char      **line;
2119         char      **priv_lines;
2120         static char *privileges_setup[] = {
2121                 "UPDATE pg_class "
2122                 "  SET relacl = E'{\"=r/\\\\\"$POSTGRES_SUPERUSERNAME\\\\\"\"}' "
2123                 "  WHERE relkind IN ('r', 'v', 'm', 'S') AND relacl IS NULL;\n",
2124                 "GRANT USAGE ON SCHEMA pg_catalog TO PUBLIC;\n",
2125                 "GRANT CREATE, USAGE ON SCHEMA public TO PUBLIC;\n",
2126                 "REVOKE ALL ON pg_largeobject FROM PUBLIC;\n",
2127                 NULL
2128         };
2129
2130         fputs(_("setting privileges on built-in objects ... "), stdout);
2131         fflush(stdout);
2132
2133         snprintf(cmd, sizeof(cmd),
2134                          "\"%s\" %s template1 >%s",
2135                          backend_exec, backend_options,
2136                          DEVNULL);
2137
2138         PG_CMD_OPEN;
2139
2140         priv_lines = replace_token(privileges_setup, "$POSTGRES_SUPERUSERNAME",
2141                                                            escape_quotes(username));
2142         for (line = priv_lines; *line != NULL; line++)
2143                 PG_CMD_PUTS(*line);
2144
2145         PG_CMD_CLOSE;
2146
2147         check_ok();
2148 }
2149
2150 /*
2151  * extract the strange version of version required for information schema
2152  * (09.08.0007abc)
2153  */
2154 static void
2155 set_info_version(void)
2156 {
2157         char       *letterversion;
2158         long            major = 0,
2159                                 minor = 0,
2160                                 micro = 0;
2161         char       *endptr;
2162         char       *vstr = pg_strdup(PG_VERSION);
2163         char       *ptr;
2164
2165         ptr = vstr + (strlen(vstr) - 1);
2166         while (ptr != vstr && (*ptr < '0' || *ptr > '9'))
2167                 ptr--;
2168         letterversion = ptr + 1;
2169         major = strtol(vstr, &endptr, 10);
2170         if (*endptr)
2171                 minor = strtol(endptr + 1, &endptr, 10);
2172         if (*endptr)
2173                 micro = strtol(endptr + 1, &endptr, 10);
2174         snprintf(infoversion, sizeof(infoversion), "%02ld.%02ld.%04ld%s",
2175                          major, minor, micro, letterversion);
2176 }
2177
2178 /*
2179  * load info schema and populate from features file
2180  */
2181 static void
2182 setup_schema(void)
2183 {
2184         PG_CMD_DECL;
2185         char      **line;
2186         char      **lines;
2187
2188         fputs(_("creating information schema ... "), stdout);
2189         fflush(stdout);
2190
2191         lines = readfile(info_schema_file);
2192
2193         /*
2194          * We use -j here to avoid backslashing stuff in information_schema.sql
2195          */
2196         snprintf(cmd, sizeof(cmd),
2197                          "\"%s\" %s -j template1 >%s",
2198                          backend_exec, backend_options,
2199                          DEVNULL);
2200
2201         PG_CMD_OPEN;
2202
2203         for (line = lines; *line != NULL; line++)
2204         {
2205                 PG_CMD_PUTS(*line);
2206                 free(*line);
2207         }
2208
2209         free(lines);
2210
2211         PG_CMD_CLOSE;
2212
2213         snprintf(cmd, sizeof(cmd),
2214                          "\"%s\" %s template1 >%s",
2215                          backend_exec, backend_options,
2216                          DEVNULL);
2217
2218         PG_CMD_OPEN;
2219
2220         PG_CMD_PRINTF1("UPDATE information_schema.sql_implementation_info "
2221                                    "  SET character_value = '%s' "
2222                                    "  WHERE implementation_info_name = 'DBMS VERSION';\n",
2223                                    infoversion);
2224
2225         PG_CMD_PRINTF1("COPY information_schema.sql_features "
2226                                    "  (feature_id, feature_name, sub_feature_id, "
2227                                    "  sub_feature_name, is_supported, comments) "
2228                                    " FROM E'%s';\n",
2229                                    escape_quotes(features_file));
2230
2231         PG_CMD_CLOSE;
2232
2233         check_ok();
2234 }
2235
2236 /*
2237  * load PL/pgsql server-side language
2238  */
2239 static void
2240 load_plpgsql(void)
2241 {
2242         PG_CMD_DECL;
2243
2244         fputs(_("loading PL/pgSQL server-side language ... "), stdout);
2245         fflush(stdout);
2246
2247         snprintf(cmd, sizeof(cmd),
2248                          "\"%s\" %s template1 >%s",
2249                          backend_exec, backend_options,
2250                          DEVNULL);
2251
2252         PG_CMD_OPEN;
2253
2254         PG_CMD_PUTS("CREATE EXTENSION plpgsql;\n");
2255
2256         PG_CMD_CLOSE;
2257
2258         check_ok();
2259 }
2260
2261 /*
2262  * clean everything up in template1
2263  */
2264 static void
2265 vacuum_db(void)
2266 {
2267         PG_CMD_DECL;
2268
2269         fputs(_("vacuuming database template1 ... "), stdout);
2270         fflush(stdout);
2271
2272         snprintf(cmd, sizeof(cmd),
2273                          "\"%s\" %s template1 >%s",
2274                          backend_exec, backend_options,
2275                          DEVNULL);
2276
2277         PG_CMD_OPEN;
2278
2279         PG_CMD_PUTS("ANALYZE;\nVACUUM FULL;\nVACUUM FREEZE;\n");
2280
2281         PG_CMD_CLOSE;
2282
2283         check_ok();
2284 }
2285
2286 /*
2287  * copy template1 to template0
2288  */
2289 static void
2290 make_template0(void)
2291 {
2292         PG_CMD_DECL;
2293         const char **line;
2294         static const char *template0_setup[] = {
2295                 "CREATE DATABASE template0;\n",
2296                 "UPDATE pg_database SET "
2297                 "       datistemplate = 't', "
2298                 "       datallowconn = 'f' "
2299                 "    WHERE datname = 'template0';\n",
2300
2301                 /*
2302                  * We use the OID of template0 to determine lastsysoid
2303                  */
2304                 "UPDATE pg_database SET datlastsysoid = "
2305                 "    (SELECT oid FROM pg_database "
2306                 "    WHERE datname = 'template0');\n",
2307
2308                 /*
2309                  * Explicitly revoke public create-schema and create-temp-table
2310                  * privileges in template1 and template0; else the latter would be on
2311                  * by default
2312                  */
2313                 "REVOKE CREATE,TEMPORARY ON DATABASE template1 FROM public;\n",
2314                 "REVOKE CREATE,TEMPORARY ON DATABASE template0 FROM public;\n",
2315
2316                 "COMMENT ON DATABASE template0 IS 'unmodifiable empty database';\n",
2317
2318                 /*
2319                  * Finally vacuum to clean up dead rows in pg_database
2320                  */
2321                 "VACUUM FULL pg_database;\n",
2322                 NULL
2323         };
2324
2325         fputs(_("copying template1 to template0 ... "), stdout);
2326         fflush(stdout);
2327
2328         snprintf(cmd, sizeof(cmd),
2329                          "\"%s\" %s template1 >%s",
2330                          backend_exec, backend_options,
2331                          DEVNULL);
2332
2333         PG_CMD_OPEN;
2334
2335         for (line = template0_setup; *line; line++)
2336                 PG_CMD_PUTS(*line);
2337
2338         PG_CMD_CLOSE;
2339
2340         check_ok();
2341 }
2342
2343 /*
2344  * copy template1 to postgres
2345  */
2346 static void
2347 make_postgres(void)
2348 {
2349         PG_CMD_DECL;
2350         const char **line;
2351         static const char *postgres_setup[] = {
2352                 "CREATE DATABASE postgres;\n",
2353                 "COMMENT ON DATABASE postgres IS 'default administrative connection database';\n",
2354                 NULL
2355         };
2356
2357         fputs(_("copying template1 to postgres ... "), stdout);
2358         fflush(stdout);
2359
2360         snprintf(cmd, sizeof(cmd),
2361                          "\"%s\" %s template1 >%s",
2362                          backend_exec, backend_options,
2363                          DEVNULL);
2364
2365         PG_CMD_OPEN;
2366
2367         for (line = postgres_setup; *line; line++)
2368                 PG_CMD_PUTS(*line);
2369
2370         PG_CMD_CLOSE;
2371
2372         check_ok();
2373 }
2374
2375 /*
2376  * fsync everything down to disk
2377  */
2378 static void
2379 perform_fsync(void)
2380 {
2381         char            pdir[MAXPGPATH];
2382
2383         fputs(_("syncing data to disk ... "), stdout);
2384         fflush(stdout);
2385
2386         /*
2387          * We need to name the parent of PGDATA.  get_parent_directory() isn't
2388          * enough here, because it can result in an empty string.
2389          */
2390         snprintf(pdir, MAXPGPATH, "%s/..", pg_data);
2391         canonicalize_path(pdir);
2392
2393         /*
2394          * Hint to the OS so that we're going to fsync each of these files soon.
2395          */
2396
2397         /* first the parent of the PGDATA directory */
2398         pre_sync_fname(pdir, true);
2399
2400         /* then recursively through the directory */
2401         walkdir(pg_data, pre_sync_fname);
2402
2403         /*
2404          * Now, do the fsync()s in the same order.
2405          */
2406
2407         /* first the parent of the PGDATA directory */
2408         fsync_fname(pdir, true);
2409
2410         /* then recursively through the directory */
2411         walkdir(pg_data, fsync_fname);
2412
2413         check_ok();
2414 }
2415
2416
2417 /*
2418  * signal handler in case we are interrupted.
2419  *
2420  * The Windows runtime docs at
2421  * http://msdn.microsoft.com/library/en-us/vclib/html/_crt_signal.asp
2422  * specifically forbid a number of things being done from a signal handler,
2423  * including IO, memory allocation and system calls, and only allow jmpbuf
2424  * if you are handling SIGFPE.
2425  *
2426  * I avoided doing the forbidden things by setting a flag instead of calling
2427  * exit_nicely() directly.
2428  *
2429  * Also note the behaviour of Windows with SIGINT, which says this:
2430  *       Note   SIGINT is not supported for any Win32 application, including
2431  *       Windows 98/Me and Windows NT/2000/XP. When a CTRL+C interrupt occurs,
2432  *       Win32 operating systems generate a new thread to specifically handle
2433  *       that interrupt. This can cause a single-thread application such as UNIX,
2434  *       to become multithreaded, resulting in unexpected behavior.
2435  *
2436  * I have no idea how to handle this. (Strange they call UNIX an application!)
2437  * So this will need some testing on Windows.
2438  */
2439 static void
2440 trapsig(int signum)
2441 {
2442         /* handle systems that reset the handler, like Windows (grr) */
2443         pqsignal(signum, trapsig);
2444         caught_signal = true;
2445 }
2446
2447 /*
2448  * call exit_nicely() if we got a signal, or else output "ok".
2449  */
2450 static void
2451 check_ok(void)
2452 {
2453         if (caught_signal)
2454         {
2455                 printf(_("caught signal\n"));
2456                 fflush(stdout);
2457                 exit_nicely();
2458         }
2459         else if (output_failed)
2460         {
2461                 printf(_("could not write to child process: %s\n"),
2462                            strerror(output_errno));
2463                 fflush(stdout);
2464                 exit_nicely();
2465         }
2466         else
2467         {
2468                 /* all seems well */
2469                 printf(_("ok\n"));
2470                 fflush(stdout);
2471         }
2472 }
2473
2474 /* Hack to suppress a warning about %x from some versions of gcc */
2475 static inline size_t
2476 my_strftime(char *s, size_t max, const char *fmt, const struct tm * tm)
2477 {
2478         return strftime(s, max, fmt, tm);
2479 }
2480
2481 /*
2482  * Determine likely date order from locale
2483  */
2484 static int
2485 locale_date_order(const char *locale)
2486 {
2487         struct tm       testtime;
2488         char            buf[128];
2489         char       *posD;
2490         char       *posM;
2491         char       *posY;
2492         char       *save;
2493         size_t          res;
2494         int                     result;
2495
2496         result = DATEORDER_MDY;         /* default */
2497
2498         save = setlocale(LC_TIME, NULL);
2499         if (!save)
2500                 return result;
2501         save = pg_strdup(save);
2502
2503         setlocale(LC_TIME, locale);
2504
2505         memset(&testtime, 0, sizeof(testtime));
2506         testtime.tm_mday = 22;
2507         testtime.tm_mon = 10;           /* November, should come out as "11" */
2508         testtime.tm_year = 133;         /* 2033 */
2509
2510         res = my_strftime(buf, sizeof(buf), "%x", &testtime);
2511
2512         setlocale(LC_TIME, save);
2513         free(save);
2514
2515         if (res == 0)
2516                 return result;
2517
2518         posM = strstr(buf, "11");
2519         posD = strstr(buf, "22");
2520         posY = strstr(buf, "33");
2521
2522         if (!posM || !posD || !posY)
2523                 return result;
2524
2525         if (posY < posM && posM < posD)
2526                 result = DATEORDER_YMD;
2527         else if (posD < posM)
2528                 result = DATEORDER_DMY;
2529         else
2530                 result = DATEORDER_MDY;
2531
2532         return result;
2533 }
2534
2535 /*
2536  * Is the locale name valid for the locale category?
2537  *
2538  * If successful, and canonname isn't NULL, a malloc'd copy of the locale's
2539  * canonical name is stored there.      This is especially useful for figuring out
2540  * what locale name "" means (ie, the environment value).  (Actually,
2541  * it seems that on most implementations that's the only thing it's good for;
2542  * we could wish that setlocale gave back a canonically spelled version of
2543  * the locale name, but typically it doesn't.)
2544  *
2545  * this should match the backend's check_locale() function
2546  */
2547 static bool
2548 check_locale_name(int category, const char *locale, char **canonname)
2549 {
2550         char       *save;
2551         char       *res;
2552
2553         if (canonname)
2554                 *canonname = NULL;              /* in case of failure */
2555
2556         save = setlocale(category, NULL);
2557         if (!save)
2558                 return false;                   /* won't happen, we hope */
2559
2560         /* save may be pointing at a modifiable scratch variable, so copy it. */
2561         save = pg_strdup(save);
2562
2563         /* set the locale with setlocale, to see if it accepts it. */
2564         res = setlocale(category, locale);
2565
2566         /* save canonical name if requested. */
2567         if (res && canonname)
2568                 *canonname = pg_strdup(res);
2569
2570         /* restore old value. */
2571         if (!setlocale(category, save))
2572                 fprintf(stderr, _("%s: failed to restore old locale \"%s\"\n"),
2573                                 progname, save);
2574         free(save);
2575
2576         /* should we exit here? */
2577         if (res == NULL)
2578                 fprintf(stderr, _("%s: invalid locale name \"%s\"\n"),
2579                                 progname, locale);
2580
2581         return (res != NULL);
2582 }
2583
2584 /*
2585  * check if the chosen encoding matches the encoding required by the locale
2586  *
2587  * this should match the similar check in the backend createdb() function
2588  */
2589 static bool
2590 check_locale_encoding(const char *locale, int user_enc)
2591 {
2592         int                     locale_enc;
2593
2594         locale_enc = pg_get_encoding_from_locale(locale, true);
2595
2596         /* See notes in createdb() to understand these tests */
2597         if (!(locale_enc == user_enc ||
2598                   locale_enc == PG_SQL_ASCII ||
2599                   locale_enc == -1 ||
2600 #ifdef WIN32
2601                   user_enc == PG_UTF8 ||
2602 #endif
2603                   user_enc == PG_SQL_ASCII))
2604         {
2605                 fprintf(stderr, _("%s: encoding mismatch\n"), progname);
2606                 fprintf(stderr,
2607                                 _("The encoding you selected (%s) and the encoding that the\n"
2608                           "selected locale uses (%s) do not match.  This would lead to\n"
2609                         "misbehavior in various character string processing functions.\n"
2610                            "Rerun %s and either do not specify an encoding explicitly,\n"
2611                                   "or choose a matching combination.\n"),
2612                                 pg_encoding_to_char(user_enc),
2613                                 pg_encoding_to_char(locale_enc),
2614                                 progname);
2615                 return false;
2616         }
2617         return true;
2618 }
2619
2620 /*
2621  * set up the locale variables
2622  *
2623  * assumes we have called setlocale(LC_ALL, "") -- see set_pglocale_pgservice
2624  */
2625 static void
2626 setlocales(void)
2627 {
2628         char       *canonname;
2629
2630         /* set empty lc_* values to locale config if set */
2631
2632         if (strlen(locale) > 0)
2633         {
2634                 if (strlen(lc_ctype) == 0)
2635                         lc_ctype = locale;
2636                 if (strlen(lc_collate) == 0)
2637                         lc_collate = locale;
2638                 if (strlen(lc_numeric) == 0)
2639                         lc_numeric = locale;
2640                 if (strlen(lc_time) == 0)
2641                         lc_time = locale;
2642                 if (strlen(lc_monetary) == 0)
2643                         lc_monetary = locale;
2644                 if (strlen(lc_messages) == 0)
2645                         lc_messages = locale;
2646         }
2647
2648         /*
2649          * canonicalize locale names, and override any missing/invalid values from
2650          * our current environment
2651          */
2652
2653         if (check_locale_name(LC_CTYPE, lc_ctype, &canonname))
2654                 lc_ctype = canonname;
2655         else
2656                 lc_ctype = pg_strdup(setlocale(LC_CTYPE, NULL));
2657         if (check_locale_name(LC_COLLATE, lc_collate, &canonname))
2658                 lc_collate = canonname;
2659         else
2660                 lc_collate = pg_strdup(setlocale(LC_COLLATE, NULL));
2661         if (check_locale_name(LC_NUMERIC, lc_numeric, &canonname))
2662                 lc_numeric = canonname;
2663         else
2664                 lc_numeric = pg_strdup(setlocale(LC_NUMERIC, NULL));
2665         if (check_locale_name(LC_TIME, lc_time, &canonname))
2666                 lc_time = canonname;
2667         else
2668                 lc_time = pg_strdup(setlocale(LC_TIME, NULL));
2669         if (check_locale_name(LC_MONETARY, lc_monetary, &canonname))
2670                 lc_monetary = canonname;
2671         else
2672                 lc_monetary = pg_strdup(setlocale(LC_MONETARY, NULL));
2673 #if defined(LC_MESSAGES) && !defined(WIN32)
2674         if (check_locale_name(LC_MESSAGES, lc_messages, &canonname))
2675                 lc_messages = canonname;
2676         else
2677                 lc_messages = pg_strdup(setlocale(LC_MESSAGES, NULL));
2678 #else
2679         /* when LC_MESSAGES is not available, use the LC_CTYPE setting */
2680         if (check_locale_name(LC_CTYPE, lc_messages, &canonname))
2681                 lc_messages = canonname;
2682         else
2683                 lc_messages = pg_strdup(setlocale(LC_CTYPE, NULL));
2684 #endif
2685 }
2686
2687 #ifdef WIN32
2688 typedef BOOL (WINAPI * __CreateRestrictedToken) (HANDLE, DWORD, DWORD, PSID_AND_ATTRIBUTES, DWORD, PLUID_AND_ATTRIBUTES, DWORD, PSID_AND_ATTRIBUTES, PHANDLE);
2689
2690 /* Windows API define missing from some versions of MingW headers */
2691 #ifndef  DISABLE_MAX_PRIVILEGE
2692 #define DISABLE_MAX_PRIVILEGE   0x1
2693 #endif
2694
2695 /*
2696  * Create a restricted token and execute the specified process with it.
2697  *
2698  * Returns 0 on failure, non-zero on success, same as CreateProcess().
2699  *
2700  * On NT4, or any other system not containing the required functions, will
2701  * NOT execute anything.
2702  */
2703 static int
2704 CreateRestrictedProcess(char *cmd, PROCESS_INFORMATION *processInfo)
2705 {
2706         BOOL            b;
2707         STARTUPINFO si;
2708         HANDLE          origToken;
2709         HANDLE          restrictedToken;
2710         SID_IDENTIFIER_AUTHORITY NtAuthority = {SECURITY_NT_AUTHORITY};
2711         SID_AND_ATTRIBUTES dropSids[2];
2712         __CreateRestrictedToken _CreateRestrictedToken = NULL;
2713         HANDLE          Advapi32Handle;
2714
2715         ZeroMemory(&si, sizeof(si));
2716         si.cb = sizeof(si);
2717
2718         Advapi32Handle = LoadLibrary("ADVAPI32.DLL");
2719         if (Advapi32Handle != NULL)
2720         {
2721                 _CreateRestrictedToken = (__CreateRestrictedToken) GetProcAddress(Advapi32Handle, "CreateRestrictedToken");
2722         }
2723
2724         if (_CreateRestrictedToken == NULL)
2725         {
2726                 fprintf(stderr, _("%s: WARNING: cannot create restricted tokens on this platform\n"), progname);
2727                 if (Advapi32Handle != NULL)
2728                         FreeLibrary(Advapi32Handle);
2729                 return 0;
2730         }
2731
2732         /* Open the current token to use as a base for the restricted one */
2733         if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, &origToken))
2734         {
2735                 fprintf(stderr, _("%s: could not open process token: error code %lu\n"), progname, GetLastError());
2736                 return 0;
2737         }
2738
2739         /* Allocate list of SIDs to remove */
2740         ZeroMemory(&dropSids, sizeof(dropSids));
2741         if (!AllocateAndInitializeSid(&NtAuthority, 2,
2742                  SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0,
2743                                                                   0, &dropSids[0].Sid) ||
2744                 !AllocateAndInitializeSid(&NtAuthority, 2,
2745         SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_POWER_USERS, 0, 0, 0, 0, 0,
2746                                                                   0, &dropSids[1].Sid))
2747         {
2748                 fprintf(stderr, _("%s: could not to allocate SIDs: error code %lu\n"), progname, GetLastError());
2749                 return 0;
2750         }
2751
2752         b = _CreateRestrictedToken(origToken,
2753                                                            DISABLE_MAX_PRIVILEGE,
2754                                                            sizeof(dropSids) / sizeof(dropSids[0]),
2755                                                            dropSids,
2756                                                            0, NULL,
2757                                                            0, NULL,
2758                                                            &restrictedToken);
2759
2760         FreeSid(dropSids[1].Sid);
2761         FreeSid(dropSids[0].Sid);
2762         CloseHandle(origToken);
2763         FreeLibrary(Advapi32Handle);
2764
2765         if (!b)
2766         {
2767                 fprintf(stderr, _("%s: could not create restricted token: error code %lu\n"), progname, GetLastError());
2768                 return 0;
2769         }
2770
2771 #ifndef __CYGWIN__
2772         AddUserToTokenDacl(restrictedToken);
2773 #endif
2774
2775         if (!CreateProcessAsUser(restrictedToken,
2776                                                          NULL,
2777                                                          cmd,
2778                                                          NULL,
2779                                                          NULL,
2780                                                          TRUE,
2781                                                          CREATE_SUSPENDED,
2782                                                          NULL,
2783                                                          NULL,
2784                                                          &si,
2785                                                          processInfo))
2786
2787         {
2788                 fprintf(stderr, _("%s: could not start process for command \"%s\": error code %lu\n"), progname, cmd, GetLastError());
2789                 return 0;
2790         }
2791
2792         return ResumeThread(processInfo->hThread);
2793 }
2794 #endif
2795
2796 /*
2797  * print help text
2798  */
2799 static void
2800 usage(const char *progname)
2801 {
2802         printf(_("%s initializes a PostgreSQL database cluster.\n\n"), progname);
2803         printf(_("Usage:\n"));
2804         printf(_("  %s [OPTION]... [DATADIR]\n"), progname);
2805         printf(_("\nOptions:\n"));
2806         printf(_("  -A, --auth=METHOD         default authentication method for local connections\n"));
2807         printf(_("      --auth-host=METHOD    default authentication method for local TCP/IP connections\n"));
2808         printf(_("      --auth-local=METHOD   default authentication method for local-socket connections\n"));
2809         printf(_(" [-D, --pgdata=]DATADIR     location for this database cluster\n"));
2810         printf(_("  -E, --encoding=ENCODING   set default encoding for new databases\n"));
2811         printf(_("      --locale=LOCALE       set default locale for new databases\n"));
2812         printf(_("      --lc-collate=, --lc-ctype=, --lc-messages=LOCALE\n"
2813                          "      --lc-monetary=, --lc-numeric=, --lc-time=LOCALE\n"
2814                          "                            set default locale in the respective category for\n"
2815                          "                            new databases (default taken from environment)\n"));
2816         printf(_("      --no-locale           equivalent to --locale=C\n"));
2817         printf(_("      --pwfile=FILE         read password for the new superuser from file\n"));
2818         printf(_("  -T, --text-search-config=CFG\n"
2819                  "                            default text search configuration\n"));
2820         printf(_("  -U, --username=NAME       database superuser name\n"));
2821         printf(_("  -W, --pwprompt            prompt for a password for the new superuser\n"));
2822         printf(_("  -X, --xlogdir=XLOGDIR     location for the transaction log directory\n"));
2823         printf(_("\nLess commonly used options:\n"));
2824         printf(_("  -d, --debug               generate lots of debugging output\n"));
2825         printf(_("  -k, --data-checksums      use data page checksums\n"));
2826         printf(_("  -L DIRECTORY              where to find the input files\n"));
2827         printf(_("  -n, --noclean             do not clean up after errors\n"));
2828         printf(_("  -N, --nosync              do not wait for changes to be written safely to disk\n"));
2829         printf(_("  -s, --show                show internal settings\n"));
2830         printf(_("  -S, --sync-only           only sync data directory\n"));
2831         printf(_("\nOther options:\n"));
2832         printf(_("  -V, --version             output version information, then exit\n"));
2833         printf(_("  -?, --help                show this help, then exit\n"));
2834         printf(_("\nIf the data directory is not specified, the environment variable PGDATA\n"
2835                          "is used.\n"));
2836         printf(_("\nReport bugs to <pgsql-bugs@postgresql.org>.\n"));
2837 }
2838
2839 static void
2840 check_authmethod_unspecified(const char **authmethod)
2841 {
2842         if (*authmethod == NULL || strlen(*authmethod) == 0)
2843         {
2844                 authwarning = _("\nWARNING: enabling \"trust\" authentication for local connections\n"
2845                                                 "You can change this by editing pg_hba.conf or using the option -A, or\n"
2846                         "--auth-local and --auth-host, the next time you run initdb.\n");
2847                 *authmethod = "trust";
2848         }
2849 }
2850
2851 static void
2852 check_authmethod_valid(const char *authmethod, const char **valid_methods, const char *conntype)
2853 {
2854         const char **p;
2855
2856         for (p = valid_methods; *p; p++)
2857         {
2858                 if (strcmp(authmethod, *p) == 0)
2859                         return;
2860                 /* with space = param */
2861                 if (strchr(authmethod, ' '))
2862                         if (strncmp(authmethod, *p, (authmethod - strchr(authmethod, ' '))) == 0)
2863                                 return;
2864         }
2865
2866         fprintf(stderr, _("%s: invalid authentication method \"%s\" for \"%s\" connections\n"),
2867                         progname, authmethod, conntype);
2868         exit(1);
2869 }
2870
2871 static void
2872 check_need_password(const char *authmethodlocal, const char *authmethodhost)
2873 {
2874         if ((strcmp(authmethodlocal, "md5") == 0 ||
2875                  strcmp(authmethodlocal, "password") == 0) &&
2876                 (strcmp(authmethodhost, "md5") == 0 ||
2877                  strcmp(authmethodhost, "password") == 0) &&
2878                 !(pwprompt || pwfilename))
2879         {
2880                 fprintf(stderr, _("%s: must specify a password for the superuser to enable %s authentication\n"), progname,
2881                                 (strcmp(authmethodlocal, "md5") == 0 ||
2882                                  strcmp(authmethodlocal, "password") == 0)
2883                                 ? authmethodlocal
2884                                 : authmethodhost);
2885                 exit(1);
2886         }
2887 }
2888
2889 void
2890 get_restricted_token(void)
2891 {
2892 #ifdef WIN32
2893         /*
2894          * Before we execute another program, make sure that we are running with a
2895          * restricted token. If not, re-execute ourselves with one.
2896          */
2897
2898         if ((restrict_env = getenv("PG_RESTRICT_EXEC")) == NULL
2899                 || strcmp(restrict_env, "1") != 0)
2900         {
2901                 PROCESS_INFORMATION pi;
2902                 char       *cmdline;
2903
2904                 ZeroMemory(&pi, sizeof(pi));
2905
2906                 cmdline = pg_strdup(GetCommandLine());
2907
2908                 putenv("PG_RESTRICT_EXEC=1");
2909
2910                 if (!CreateRestrictedProcess(cmdline, &pi))
2911                 {
2912                         fprintf(stderr, _("%s: could not re-execute with restricted token: error code %lu\n"), progname, GetLastError());
2913                 }
2914                 else
2915                 {
2916                         /*
2917                          * Successfully re-execed. Now wait for child process to capture
2918                          * exitcode.
2919                          */
2920                         DWORD           x;
2921
2922                         CloseHandle(pi.hThread);
2923                         WaitForSingleObject(pi.hProcess, INFINITE);
2924
2925                         if (!GetExitCodeProcess(pi.hProcess, &x))
2926                         {
2927                                 fprintf(stderr, _("%s: could not get exit code from subprocess: error code %lu\n"), progname, GetLastError());
2928                                 exit(1);
2929                         }
2930                         exit(x);
2931                 }
2932         }
2933 #endif
2934 }
2935
2936 void
2937 setup_pgdata(void)
2938 {
2939         char       *pgdata_get_env,
2940                            *pgdata_set_env;
2941
2942         if (strlen(pg_data) == 0)
2943         {
2944                 pgdata_get_env = getenv("PGDATA");
2945                 if (pgdata_get_env && strlen(pgdata_get_env))
2946                 {
2947                         /* PGDATA found */
2948                         pg_data = pg_strdup(pgdata_get_env);
2949                 }
2950                 else
2951                 {
2952                         fprintf(stderr,
2953                                         _("%s: no data directory specified\n"
2954                                           "You must identify the directory where the data for this database system\n"
2955                                           "will reside.  Do this with either the invocation option -D or the\n"
2956                                           "environment variable PGDATA.\n"),
2957                                         progname);
2958                         exit(1);
2959                 }
2960         }
2961
2962         pgdata_native = pg_strdup(pg_data);
2963         canonicalize_path(pg_data);
2964
2965         /*
2966          * we have to set PGDATA for postgres rather than pass it on the command
2967          * line to avoid dumb quoting problems on Windows, and we would especially
2968          * need quotes otherwise on Windows because paths there are most likely to
2969          * have embedded spaces.
2970          */
2971         pgdata_set_env = psprintf("PGDATA=%s", pg_data);
2972         putenv(pgdata_set_env);
2973 }
2974
2975
2976 void
2977 setup_bin_paths(const char *argv0)
2978 {
2979         int                     ret;
2980
2981         if ((ret = find_other_exec(argv0, "postgres", PG_BACKEND_VERSIONSTR,
2982                                                            backend_exec)) < 0)
2983         {
2984                 char            full_path[MAXPGPATH];
2985
2986                 if (find_my_exec(argv0, full_path) < 0)
2987                         strlcpy(full_path, progname, sizeof(full_path));
2988
2989                 if (ret == -1)
2990                         fprintf(stderr,
2991                                         _("The program \"postgres\" is needed by %s "
2992                                           "but was not found in the\n"
2993                                           "same directory as \"%s\".\n"
2994                                           "Check your installation.\n"),
2995                                         progname, full_path);
2996                 else
2997                         fprintf(stderr,
2998                                         _("The program \"postgres\" was found by \"%s\"\n"
2999                                           "but was not the same version as %s.\n"
3000                                           "Check your installation.\n"),
3001                                         full_path, progname);
3002                 exit(1);
3003         }
3004
3005         /* store binary directory */
3006         strcpy(bin_path, backend_exec);
3007         *last_dir_separator(bin_path) = '\0';
3008         canonicalize_path(bin_path);
3009
3010         if (!share_path)
3011         {
3012                 share_path = pg_malloc(MAXPGPATH);
3013                 get_share_path(backend_exec, share_path);
3014         }
3015         else if (!is_absolute_path(share_path))
3016         {
3017                 fprintf(stderr, _("%s: input file location must be an absolute path\n"), progname);
3018                 exit(1);
3019         }
3020
3021         canonicalize_path(share_path);
3022 }
3023
3024 void
3025 setup_locale_encoding(void)
3026 {
3027         int                     user_enc;
3028
3029         setlocales();
3030
3031         if (strcmp(lc_ctype, lc_collate) == 0 &&
3032                 strcmp(lc_ctype, lc_time) == 0 &&
3033                 strcmp(lc_ctype, lc_numeric) == 0 &&
3034                 strcmp(lc_ctype, lc_monetary) == 0 &&
3035                 strcmp(lc_ctype, lc_messages) == 0)
3036                 printf(_("The database cluster will be initialized with locale \"%s\".\n"), lc_ctype);
3037         else
3038         {
3039                 printf(_("The database cluster will be initialized with locales\n"
3040                                  "  COLLATE:  %s\n"
3041                                  "  CTYPE:    %s\n"
3042                                  "  MESSAGES: %s\n"
3043                                  "  MONETARY: %s\n"
3044                                  "  NUMERIC:  %s\n"
3045                                  "  TIME:     %s\n"),
3046                            lc_collate,
3047                            lc_ctype,
3048                            lc_messages,
3049                            lc_monetary,
3050                            lc_numeric,
3051                            lc_time);
3052         }
3053
3054         if (strlen(encoding) == 0)
3055         {
3056                 int                     ctype_enc;
3057
3058                 ctype_enc = pg_get_encoding_from_locale(lc_ctype, true);
3059
3060                 if (ctype_enc == -1)
3061                 {
3062                         /* Couldn't recognize the locale's codeset */
3063                         fprintf(stderr, _("%s: could not find suitable encoding for locale \"%s\"\n"),
3064                                         progname, lc_ctype);
3065                         fprintf(stderr, _("Rerun %s with the -E option.\n"), progname);
3066                         fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
3067                                         progname);
3068                         exit(1);
3069                 }
3070                 else if (!pg_valid_server_encoding_id(ctype_enc))
3071                 {
3072                         /*
3073                          * We recognized it, but it's not a legal server encoding. On
3074                          * Windows, UTF-8 works with any locale, so we can fall back to
3075                          * UTF-8.
3076                          */
3077 #ifdef WIN32
3078                         printf(_("Encoding \"%s\" implied by locale is not allowed as a server-side encoding.\n"
3079                         "The default database encoding will be set to \"%s\" instead.\n"),
3080                                    pg_encoding_to_char(ctype_enc),
3081                                    pg_encoding_to_char(PG_UTF8));
3082                         ctype_enc = PG_UTF8;
3083                         encodingid = encodingid_to_string(ctype_enc);
3084 #else
3085                         fprintf(stderr,
3086                            _("%s: locale \"%s\" requires unsupported encoding \"%s\"\n"),
3087                                         progname, lc_ctype, pg_encoding_to_char(ctype_enc));
3088                         fprintf(stderr,
3089                           _("Encoding \"%s\" is not allowed as a server-side encoding.\n"
3090                                 "Rerun %s with a different locale selection.\n"),
3091                                         pg_encoding_to_char(ctype_enc), progname);
3092                         exit(1);
3093 #endif
3094                 }
3095                 else
3096                 {
3097                         encodingid = encodingid_to_string(ctype_enc);
3098                         printf(_("The default database encoding has accordingly been set to \"%s\".\n"),
3099                                    pg_encoding_to_char(ctype_enc));
3100                 }
3101         }
3102         else
3103                 encodingid = get_encoding_id(encoding);
3104
3105         user_enc = atoi(encodingid);
3106         if (!check_locale_encoding(lc_ctype, user_enc) ||
3107                 !check_locale_encoding(lc_collate, user_enc))
3108                 exit(1);                                /* check_locale_encoding printed the error */
3109
3110 }
3111
3112
3113 void
3114 setup_data_file_paths(void)
3115 {
3116         set_input(&bki_file, "postgres.bki");
3117         set_input(&desc_file, "postgres.description");
3118         set_input(&shdesc_file, "postgres.shdescription");
3119         set_input(&hba_file, "pg_hba.conf.sample");
3120         set_input(&ident_file, "pg_ident.conf.sample");
3121         set_input(&conf_file, "postgresql.conf.sample");
3122         set_input(&conversion_file, "conversion_create.sql");
3123         set_input(&dictionary_file, "snowball_create.sql");
3124         set_input(&info_schema_file, "information_schema.sql");
3125         set_input(&features_file, "sql_features.txt");
3126         set_input(&system_views_file, "system_views.sql");
3127
3128         if (show_setting || debug)
3129         {
3130                 fprintf(stderr,
3131                                 "VERSION=%s\n"
3132                                 "PGDATA=%s\nshare_path=%s\nPGPATH=%s\n"
3133                                 "POSTGRES_SUPERUSERNAME=%s\nPOSTGRES_BKI=%s\n"
3134                                 "POSTGRES_DESCR=%s\nPOSTGRES_SHDESCR=%s\n"
3135                                 "POSTGRESQL_CONF_SAMPLE=%s\n"
3136                                 "PG_HBA_SAMPLE=%s\nPG_IDENT_SAMPLE=%s\n",
3137                                 PG_VERSION,
3138                                 pg_data, share_path, bin_path,
3139                                 username, bki_file,
3140                                 desc_file, shdesc_file,
3141                                 conf_file,
3142                                 hba_file, ident_file);
3143                 if (show_setting)
3144                         exit(0);
3145         }
3146
3147         check_input(bki_file);
3148         check_input(desc_file);
3149         check_input(shdesc_file);
3150         check_input(hba_file);
3151         check_input(ident_file);
3152         check_input(conf_file);
3153         check_input(conversion_file);
3154         check_input(dictionary_file);
3155         check_input(info_schema_file);
3156         check_input(features_file);
3157         check_input(system_views_file);
3158 }
3159
3160
3161 void
3162 setup_text_search(void)
3163 {
3164         if (strlen(default_text_search_config) == 0)
3165         {
3166                 default_text_search_config = find_matching_ts_config(lc_ctype);
3167                 if (default_text_search_config == NULL)
3168                 {
3169                         printf(_("%s: could not find suitable text search configuration for locale \"%s\"\n"),
3170                                    progname, lc_ctype);
3171                         default_text_search_config = "simple";
3172                 }
3173         }
3174         else
3175         {
3176                 const char *checkmatch = find_matching_ts_config(lc_ctype);
3177
3178                 if (checkmatch == NULL)
3179                 {
3180                         printf(_("%s: warning: suitable text search configuration for locale \"%s\" is unknown\n"),
3181                                    progname, lc_ctype);
3182                 }
3183                 else if (strcmp(checkmatch, default_text_search_config) != 0)
3184                 {
3185                         printf(_("%s: warning: specified text search configuration \"%s\" might not match locale \"%s\"\n"),
3186                                    progname, default_text_search_config, lc_ctype);
3187                 }
3188         }
3189
3190         printf(_("The default text search configuration will be set to \"%s\".\n"),
3191                    default_text_search_config);
3192
3193 }
3194
3195
3196 void
3197 setup_signals(void)
3198 {
3199         /* some of these are not valid on Windows */
3200 #ifdef SIGHUP
3201         pqsignal(SIGHUP, trapsig);
3202 #endif
3203 #ifdef SIGINT
3204         pqsignal(SIGINT, trapsig);
3205 #endif
3206 #ifdef SIGQUIT
3207         pqsignal(SIGQUIT, trapsig);
3208 #endif
3209 #ifdef SIGTERM
3210         pqsignal(SIGTERM, trapsig);
3211 #endif
3212
3213         /* Ignore SIGPIPE when writing to backend, so we can clean up */
3214 #ifdef SIGPIPE
3215         pqsignal(SIGPIPE, SIG_IGN);
3216 #endif
3217
3218         /* Prevent SIGSYS so we can probe for kernel calls that might not work */
3219 #ifdef SIGSYS
3220         pqsignal(SIGSYS, SIG_IGN);
3221 #endif
3222 }
3223
3224
3225 void
3226 create_data_directory(void)
3227 {
3228         int                     ret;
3229
3230         switch ((ret = pg_check_dir(pg_data)))
3231         {
3232                 case 0:
3233                         /* PGDATA not there, must create it */
3234                         printf(_("creating directory %s ... "),
3235                                    pg_data);
3236                         fflush(stdout);
3237
3238                         if (!mkdatadir(NULL))
3239                                 exit_nicely();
3240                         else
3241                                 check_ok();
3242
3243                         made_new_pgdata = true;
3244                         break;
3245
3246                 case 1:
3247                         /* Present but empty, fix permissions and use it */
3248                         printf(_("fixing permissions on existing directory %s ... "),
3249                                    pg_data);
3250                         fflush(stdout);
3251
3252                         if (chmod(pg_data, S_IRWXU) != 0)
3253                         {
3254                                 fprintf(stderr, _("%s: could not change permissions of directory \"%s\": %s\n"),
3255                                                 progname, pg_data, strerror(errno));
3256                                 exit_nicely();
3257                         }
3258                         else
3259                                 check_ok();
3260
3261                         found_existing_pgdata = true;
3262                         break;
3263
3264                 case 2:
3265                 case 3:
3266                 case 4:
3267                         /* Present and not empty */
3268                         fprintf(stderr,
3269                                         _("%s: directory \"%s\" exists but is not empty\n"),
3270                                         progname, pg_data);
3271                         if (ret != 4)
3272                                 warn_on_mount_point(ret);
3273                         else
3274                                 fprintf(stderr,
3275                                                 _("If you want to create a new database system, either remove or empty\n"
3276                                                   "the directory \"%s\" or run %s\n"
3277                                                   "with an argument other than \"%s\".\n"),
3278                                                 pg_data, progname, pg_data);
3279                         exit(1);                        /* no further message needed */
3280
3281                 default:
3282                         /* Trouble accessing directory */
3283                         fprintf(stderr, _("%s: could not access directory \"%s\": %s\n"),
3284                                         progname, pg_data, strerror(errno));
3285                         exit_nicely();
3286         }
3287 }
3288
3289
3290 void
3291 create_xlog_symlink(void)
3292 {
3293         /* Create transaction log symlink, if required */
3294         if (strcmp(xlog_dir, "") != 0)
3295         {
3296                 char       *linkloc;
3297                 int                     ret;
3298
3299                 /* clean up xlog directory name, check it's absolute */
3300                 canonicalize_path(xlog_dir);
3301                 if (!is_absolute_path(xlog_dir))
3302                 {
3303                         fprintf(stderr, _("%s: transaction log directory location must be an absolute path\n"), progname);
3304                         exit_nicely();
3305                 }
3306
3307                 /* check if the specified xlog directory exists/is empty */
3308                 switch ((ret = pg_check_dir(xlog_dir)))
3309                 {
3310                         case 0:
3311                                 /* xlog directory not there, must create it */
3312                                 printf(_("creating directory %s ... "),
3313                                            xlog_dir);
3314                                 fflush(stdout);
3315
3316                                 if (pg_mkdir_p(xlog_dir, S_IRWXU) != 0)
3317                                 {
3318                                         fprintf(stderr, _("%s: could not create directory \"%s\": %s\n"),
3319                                                         progname, xlog_dir, strerror(errno));
3320                                         exit_nicely();
3321                                 }
3322                                 else
3323                                         check_ok();
3324
3325                                 made_new_xlogdir = true;
3326                                 break;
3327
3328                         case 1:
3329                                 /* Present but empty, fix permissions and use it */
3330                                 printf(_("fixing permissions on existing directory %s ... "),
3331                                            xlog_dir);
3332                                 fflush(stdout);
3333
3334                                 if (chmod(xlog_dir, S_IRWXU) != 0)
3335                                 {
3336                                         fprintf(stderr, _("%s: could not change permissions of directory \"%s\": %s\n"),
3337                                                         progname, xlog_dir, strerror(errno));
3338                                         exit_nicely();
3339                                 }
3340                                 else
3341                                         check_ok();
3342
3343                                 found_existing_xlogdir = true;
3344                                 break;
3345
3346                         case 2:
3347                         case 3:
3348                         case 4:
3349                                 /* Present and not empty */
3350                                 fprintf(stderr,
3351                                                 _("%s: directory \"%s\" exists but is not empty\n"),
3352                                                 progname, xlog_dir);
3353                                 if (ret != 4)
3354                                         warn_on_mount_point(ret);
3355                                 else
3356                                         fprintf(stderr,
3357                                                         _("If you want to store the transaction log there, either\n"
3358                                                           "remove or empty the directory \"%s\".\n"),
3359                                                         xlog_dir);
3360                                 exit_nicely();
3361
3362                         default:
3363                                 /* Trouble accessing directory */
3364                                 fprintf(stderr, _("%s: could not access directory \"%s\": %s\n"),
3365                                                 progname, xlog_dir, strerror(errno));
3366                                 exit_nicely();
3367                 }
3368
3369                 /* form name of the place where the symlink must go */
3370                 linkloc = psprintf("%s/pg_xlog", pg_data);
3371
3372 #ifdef HAVE_SYMLINK
3373                 if (symlink(xlog_dir, linkloc) != 0)
3374                 {
3375                         fprintf(stderr, _("%s: could not create symbolic link \"%s\": %s\n"),
3376                                         progname, linkloc, strerror(errno));
3377                         exit_nicely();
3378                 }
3379 #else
3380                 fprintf(stderr, _("%s: symlinks are not supported on this platform"));
3381                 exit_nicely();
3382 #endif
3383                 free(linkloc);
3384         }
3385 }
3386
3387
3388 void
3389 warn_on_mount_point(int error)
3390 {
3391         if (error == 2)
3392                 fprintf(stderr,
3393                                 _("It contains a dot-prefixed/invisible file, perhaps due to it being a mount point.\n"));
3394         else if (error == 3)
3395                 fprintf(stderr,
3396                                 _("It contains a lost+found directory, perhaps due to it being a mount point.\n"));
3397
3398         fprintf(stderr,
3399                         _("Using a mount point directly as the data directory is not recommended.\n"
3400                           "Create a subdirectory under the mount point.\n"));
3401 }
3402
3403
3404 void
3405 initialize_data_directory(void)
3406 {
3407         int                     i;
3408
3409         setup_signals();
3410
3411         umask(S_IRWXG | S_IRWXO);
3412
3413         create_data_directory();
3414
3415         create_xlog_symlink();
3416
3417         /* Create required subdirectories */
3418         printf(_("creating subdirectories ... "));
3419         fflush(stdout);
3420
3421         for (i = 0; i < (sizeof(subdirs) / sizeof(char *)); i++)
3422         {
3423                 if (!mkdatadir(subdirs[i]))
3424                         exit_nicely();
3425         }
3426
3427         check_ok();
3428
3429         /* Top level PG_VERSION is checked by bootstrapper, so make it first */
3430         write_version_file(NULL);
3431
3432         /* Select suitable configuration settings */
3433         set_null_conf();
3434         test_config_settings();
3435
3436         /* Now create all the text config files */
3437         setup_config();
3438
3439         /* Bootstrap template1 */
3440         bootstrap_template1();
3441
3442         /*
3443          * Make the per-database PG_VERSION for template1 only after init'ing it
3444          */
3445         write_version_file("base/1");
3446
3447         /* Create the stuff we don't need to use bootstrap mode for */
3448
3449         setup_auth();
3450         if (pwprompt || pwfilename)
3451                 get_set_pwd();
3452
3453         setup_depend();
3454
3455         setup_sysviews();
3456
3457         setup_description();
3458
3459         setup_collation();
3460
3461         setup_conversion();
3462
3463         setup_dictionary();
3464
3465         setup_privileges();
3466
3467         setup_schema();
3468
3469         load_plpgsql();
3470
3471         vacuum_db();
3472
3473         make_template0();
3474
3475         make_postgres();
3476 }
3477
3478
3479 int
3480 main(int argc, char *argv[])
3481 {
3482         static struct option long_options[] = {
3483                 {"pgdata", required_argument, NULL, 'D'},
3484                 {"encoding", required_argument, NULL, 'E'},
3485                 {"locale", required_argument, NULL, 1},
3486                 {"lc-collate", required_argument, NULL, 2},
3487                 {"lc-ctype", required_argument, NULL, 3},
3488                 {"lc-monetary", required_argument, NULL, 4},
3489                 {"lc-numeric", required_argument, NULL, 5},
3490                 {"lc-time", required_argument, NULL, 6},
3491                 {"lc-messages", required_argument, NULL, 7},
3492                 {"no-locale", no_argument, NULL, 8},
3493                 {"text-search-config", required_argument, NULL, 'T'},
3494                 {"auth", required_argument, NULL, 'A'},
3495                 {"auth-local", required_argument, NULL, 10},
3496                 {"auth-host", required_argument, NULL, 11},
3497                 {"pwprompt", no_argument, NULL, 'W'},
3498                 {"pwfile", required_argument, NULL, 9},
3499                 {"username", required_argument, NULL, 'U'},
3500                 {"help", no_argument, NULL, '?'},
3501                 {"version", no_argument, NULL, 'V'},
3502                 {"debug", no_argument, NULL, 'd'},
3503                 {"show", no_argument, NULL, 's'},
3504                 {"noclean", no_argument, NULL, 'n'},
3505                 {"nosync", no_argument, NULL, 'N'},
3506                 {"sync-only", no_argument, NULL, 'S'},
3507                 {"xlogdir", required_argument, NULL, 'X'},
3508                 {"data-checksums", no_argument, NULL, 'k'},
3509                 {NULL, 0, NULL, 0}
3510         };
3511
3512         /*
3513          * options with no short version return a low integer, the rest return
3514          * their short version value
3515          */
3516         int                     c;
3517         int                     option_index;
3518         char       *effective_user;
3519         char            bin_dir[MAXPGPATH];
3520
3521         progname = get_progname(argv[0]);
3522         set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("initdb"));
3523
3524         if (argc > 1)
3525         {
3526                 if (strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-?") == 0)
3527                 {
3528                         usage(progname);
3529                         exit(0);
3530                 }
3531                 if (strcmp(argv[1], "--version") == 0 || strcmp(argv[1], "-V") == 0)
3532                 {
3533                         puts("initdb (PostgreSQL) " PG_VERSION);
3534                         exit(0);
3535                 }
3536         }
3537
3538         /* process command-line options */
3539
3540         while ((c = getopt_long(argc, argv, "dD:E:kL:nNU:WA:sST:X:", long_options, &option_index)) != -1)
3541         {
3542                 switch (c)
3543                 {
3544                         case 'A':
3545                                 authmethodlocal = authmethodhost = pg_strdup(optarg);
3546
3547                                 /*
3548                                  * When ident is specified, use peer for local connections.
3549                                  * Mirrored, when peer is specified, use ident for TCP/IP
3550                                  * connections.
3551                                  */
3552                                 if (strcmp(authmethodhost, "ident") == 0)
3553                                         authmethodlocal = "peer";
3554                                 else if (strcmp(authmethodlocal, "peer") == 0)
3555                                         authmethodhost = "ident";
3556                                 break;
3557                         case 10:
3558                                 authmethodlocal = pg_strdup(optarg);
3559                                 break;
3560                         case 11:
3561                                 authmethodhost = pg_strdup(optarg);
3562                                 break;
3563                         case 'D':
3564                                 pg_data = pg_strdup(optarg);
3565                                 break;
3566                         case 'E':
3567                                 encoding = pg_strdup(optarg);
3568                                 break;
3569                         case 'W':
3570                                 pwprompt = true;
3571                                 break;
3572                         case 'U':
3573                                 username = pg_strdup(optarg);
3574                                 break;
3575                         case 'd':
3576                                 debug = true;
3577                                 printf(_("Running in debug mode.\n"));
3578                                 break;
3579                         case 'n':
3580                                 noclean = true;
3581                                 printf(_("Running in noclean mode.  Mistakes will not be cleaned up.\n"));
3582                                 break;
3583                         case 'N':
3584                                 do_sync = false;
3585                                 break;
3586                         case 'S':
3587                                 sync_only = true;
3588                                 break;
3589                         case 'k':
3590                                 data_checksums = true;
3591                                 break;
3592                         case 'L':
3593                                 share_path = pg_strdup(optarg);
3594                                 break;
3595                         case 1:
3596                                 locale = pg_strdup(optarg);
3597                                 break;
3598                         case 2:
3599                                 lc_collate = pg_strdup(optarg);
3600                                 break;
3601                         case 3:
3602                                 lc_ctype = pg_strdup(optarg);
3603                                 break;
3604                         case 4:
3605                                 lc_monetary = pg_strdup(optarg);
3606                                 break;
3607                         case 5:
3608                                 lc_numeric = pg_strdup(optarg);
3609                                 break;
3610                         case 6:
3611                                 lc_time = pg_strdup(optarg);
3612                                 break;
3613                         case 7:
3614                                 lc_messages = pg_strdup(optarg);
3615                                 break;
3616                         case 8:
3617                                 locale = "C";
3618                                 break;
3619                         case 9:
3620                                 pwfilename = pg_strdup(optarg);
3621                                 break;
3622                         case 's':
3623                                 show_setting = true;
3624                                 break;
3625                         case 'T':
3626                                 default_text_search_config = pg_strdup(optarg);
3627                                 break;
3628                         case 'X':
3629                                 xlog_dir = pg_strdup(optarg);
3630                                 break;
3631                         default:
3632                                 /* getopt_long already emitted a complaint */
3633                                 fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
3634                                                 progname);
3635                                 exit(1);
3636                 }
3637         }
3638
3639
3640         /*
3641          * Non-option argument specifies data directory as long as it wasn't
3642          * already specified with -D / --pgdata
3643          */
3644         if (optind < argc && strlen(pg_data) == 0)
3645         {
3646                 pg_data = pg_strdup(argv[optind]);
3647                 optind++;
3648         }
3649
3650         if (optind < argc)
3651         {
3652                 fprintf(stderr, _("%s: too many command-line arguments (first is \"%s\")\n"),
3653                                 progname, argv[optind]);
3654                 fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
3655                                 progname);
3656                 exit(1);
3657         }
3658
3659         /* If we only need to fsync, just to it and exit */
3660         if (sync_only)
3661         {
3662                 setup_pgdata();
3663                 perform_fsync();
3664                 return 0;
3665         }
3666
3667         if (pwprompt && pwfilename)
3668         {
3669                 fprintf(stderr, _("%s: password prompt and password file cannot be specified together\n"), progname);
3670                 exit(1);
3671         }
3672
3673         check_authmethod_unspecified(&authmethodlocal);
3674         check_authmethod_unspecified(&authmethodhost);
3675
3676         check_authmethod_valid(authmethodlocal, auth_methods_local, "local");
3677         check_authmethod_valid(authmethodhost, auth_methods_host, "host");
3678
3679         check_need_password(authmethodlocal, authmethodhost);
3680
3681         get_restricted_token();
3682
3683         setup_pgdata();
3684
3685         setup_bin_paths(argv[0]);
3686
3687         effective_user = get_id();
3688         if (strlen(username) == 0)
3689                 username = effective_user;
3690
3691         printf(_("The files belonging to this database system will be owned "
3692                          "by user \"%s\".\n"
3693                          "This user must also own the server process.\n\n"),
3694                    effective_user);
3695
3696         set_info_version();
3697
3698         setup_data_file_paths();
3699
3700         setup_locale_encoding();
3701
3702         setup_text_search();
3703
3704         printf("\n");
3705
3706         if (data_checksums)
3707                 printf(_("Data page checksums are enabled.\n"));
3708         else
3709                 printf(_("Data page checksums are disabled.\n"));
3710
3711         printf("\n");
3712
3713         initialize_data_directory();
3714
3715         if (do_sync)
3716                 perform_fsync();
3717         else
3718                 printf(_("\nSync to disk skipped.\nThe data directory might become corrupt if the operating system crashes.\n"));
3719
3720         if (authwarning != NULL)
3721                 fprintf(stderr, "%s", authwarning);
3722
3723         /* Get directory specification used to start this executable */
3724         strlcpy(bin_dir, argv[0], sizeof(bin_dir));
3725         get_parent_directory(bin_dir);
3726
3727         printf(_("\nSuccess. You can now start the database server using:\n\n"
3728                          "    %s%s%spostgres%s -D %s%s%s\n"
3729                          "or\n"
3730                          "    %s%s%spg_ctl%s -D %s%s%s -l logfile start\n\n"),
3731            QUOTE_PATH, bin_dir, (strlen(bin_dir) > 0) ? DIR_SEP : "", QUOTE_PATH,
3732                    QUOTE_PATH, pgdata_native, QUOTE_PATH,
3733            QUOTE_PATH, bin_dir, (strlen(bin_dir) > 0) ? DIR_SEP : "", QUOTE_PATH,
3734                    QUOTE_PATH, pgdata_native, QUOTE_PATH);
3735
3736         return 0;
3737 }