* Portions Copyright (c) 1994, Regents of the University of California
* Portions taken from FreeBSD.
*
- * $PostgreSQL: pgsql/src/bin/initdb/initdb.c,v 1.69 2004/11/29 01:14:45 momjian Exp $
+ * $PostgreSQL: pgsql/src/bin/initdb/initdb.c,v 1.70 2004/11/29 03:05:03 tgl Exp $
*
*-------------------------------------------------------------------------
*/
char infoversion[100];
bool caught_signal = false;
bool output_failed = false;
+int output_errno = 0;
/* defaults */
int n_connections = 10;
#endif
static char **readfile(char *path);
static void writefile(char *path, char **lines);
+static FILE *popen_check(const char *command, const char *mode);
static int mkdir_p(char *path, mode_t omode);
static void exit_nicely(void);
static char *get_id(void);
/*
* macros for running pipes to postgres
*/
-#define PG_CMD_DECL char cmd[MAXPGPATH]; char ** line ; FILE * pg
-#define PG_CMD_DECL_NOLINE char cmd[MAXPGPATH]; FILE * pg
+#define PG_CMD_DECL char cmd[MAXPGPATH]; FILE *cmdfd
#define PG_CMD_OPEN \
do { \
- fflush(stdout); \
- fflush(stderr); \
- pg = popen(cmd, "w"); \
- if (pg == NULL) \
- exit_nicely(); \
+ cmdfd = popen_check(cmd, "w"); \
+ if (cmdfd == NULL) \
+ exit_nicely(); /* message already printed by popen_check */ \
} while (0)
#define PG_CMD_CLOSE \
do { \
- if (pclose_check(pg)) \
- exit_nicely(); \
+ if (pclose_check(cmdfd)) \
+ exit_nicely(); /* message already printed by pclose_check */ \
} while (0)
-#define PG_CMD_PUTLINE \
+#define PG_CMD_PUTS(line) \
do { \
- if (fputs(*line, pg) < 0 || fflush(pg) < 0) \
- output_failed = true; \
+ if (fputs(line, cmdfd) < 0 || fflush(cmdfd) < 0) \
+ output_failed = true, output_errno = errno; \
+} while (0)
+
+#define PG_CMD_PRINTF1(fmt, arg1) \
+do { \
+ if (fprintf(cmdfd, fmt, arg1) < 0 || fflush(cmdfd) < 0) \
+ output_failed = true, output_errno = errno; \
+} while (0)
+
+#define PG_CMD_PRINTF2(fmt, arg1, arg2) \
+do { \
+ if (fprintf(cmdfd, fmt, arg1, arg2) < 0 || fflush(cmdfd) < 0) \
+ output_failed = true, output_errno = errno; \
} while (0)
#ifndef WIN32
for (line = lines; *line != NULL; line++)
{
if (fputs(*line, out_file) < 0)
+ {
+ fprintf(stderr, _("%s: could not write file \"%s\": %s\n"),
+ progname, path, strerror(errno));
exit_nicely();
+ }
free(*line);
}
if (fclose(out_file))
+ {
+ fprintf(stderr, _("%s: could not write file \"%s\": %s\n"),
+ progname, path, strerror(errno));
exit_nicely();
+ }
+}
+
+/*
+ * Open a subcommand with suitable error messaging
+ */
+static FILE *
+popen_check(const char *command, const char *mode)
+{
+ FILE *cmdfd;
+
+ fflush(stdout);
+ fflush(stderr);
+ errno = 0;
+ cmdfd = popen(command, mode);
+ if (cmdfd == NULL)
+ fprintf(stderr, _("%s: could not execute command \"%s\": %s\n"),
+ progname, command, strerror(errno));
+ return cmdfd;
}
/* source stolen from FreeBSD /src/bin/mkdir/mkdir.c and adapted */
static void
exit_nicely(void)
{
- fprintf(stderr, _("%s: failed\n"), progname);
-
if (!noclean)
{
if (made_new_pgdata)
fprintf(stderr, _("%s: removing data directory \"%s\"\n"),
progname, pg_data);
if (!rmtree(pg_data, true))
- fprintf(stderr, _("%s: failed\n"), progname);
+ fprintf(stderr, _("%s: failed to remove data directory\n"),
+ progname);
}
else if (found_existing_pgdata)
{
_("%s: removing contents of data directory \"%s\"\n"),
progname, pg_data);
if (!rmtree(pg_data, false))
- fprintf(stderr, _("%s: failed\n"), progname);
+ fprintf(stderr, _("%s: failed to remove contents of data directory\n"),
+ progname);
}
/* otherwise died during startup, do nothing! */
}
else
strcpy(path, pg_data);
- return (mkdir_p(path, 0700) == 0);
+ if (mkdir_p(path, 0700) == 0)
+ return true;
+
+ fprintf(stderr, _("%s: could not create directory \"%s\": %s\n"),
+ progname, path, strerror(errno));
+
+ return false;
}
progname, path);
exit(1);
}
-
}
/*
}
version_file = fopen(path, PG_BINARY_W);
if (version_file == NULL)
+ {
+ fprintf(stderr, _("%s: could not open file \"%s\" for writing: %s\n"),
+ progname, path, strerror(errno));
exit_nicely();
- fprintf(version_file, "%s\n", short_version);
- if (fclose(version_file))
+ }
+ if (fprintf(version_file, "%s\n", short_version) < 0 ||
+ fclose(version_file))
+ {
+ fprintf(stderr, _("%s: could not write file \"%s\": %s\n"),
+ progname, path, strerror(errno));
exit_nicely();
+ }
}
/*
path = xmalloc(strlen(pg_data) + 17);
sprintf(path, "%s/postgresql.conf", pg_data);
conf_file = fopen(path, PG_BINARY_W);
- if (conf_file == NULL || fclose(conf_file))
+ if (conf_file == NULL)
+ {
+ fprintf(stderr, _("%s: could not open file \"%s\" for writing: %s\n"),
+ progname, path, strerror(errno));
exit_nicely();
+ }
+ if (fclose(conf_file))
+ {
+ fprintf(stderr, _("%s: could not write file \"%s\": %s\n"),
+ progname, path, strerror(errno));
+ exit_nicely();
+ }
}
/*
static void
bootstrap_template1(char *short_version)
{
+ PG_CMD_DECL;
+ char **line;
char *talkargs = "";
char **bki_lines;
char headerline[MAXPGPATH];
- PG_CMD_DECL;
-
printf(_("creating template1 database in %s/base/1 ... "), pg_data);
fflush(stdout);
"using the option -L.\n"),
progname, bki_file, PG_VERSION);
exit_nicely();
-
}
bki_lines = replace_token(bki_lines, "POSTGRES", effective_user);
for (line = bki_lines; *line != NULL; line++)
{
- PG_CMD_PUTLINE;
+ PG_CMD_PUTS(*line);
free(*line);
}
static void
setup_shadow(void)
{
- char *pg_shadow_setup[] = {
+ PG_CMD_DECL;
+ char **line;
+ static char *pg_shadow_setup[] = {
/*
* Create a trigger so that direct updates to pg_shadow will be
* written to the flat password/group files pg_pwd and pg_group
NULL
};
- PG_CMD_DECL;
-
fputs(_("initializing pg_shadow ... "), stdout);
fflush(stdout);
PG_CMD_OPEN;
for (line = pg_shadow_setup; *line != NULL; line++)
- PG_CMD_PUTLINE;
+ PG_CMD_PUTS(*line);
PG_CMD_CLOSE;
static void
get_set_pwd(void)
{
- PG_CMD_DECL_NOLINE;
+ PG_CMD_DECL;
char *pwd1,
*pwd2;
PG_CMD_OPEN;
- if (fprintf(pg,
- "ALTER USER \"%s\" WITH PASSWORD '%s';\n", effective_user, pwd1) < 0)
- {
- /* write failure */
- exit_nicely();
- }
- fflush(pg);
+ PG_CMD_PRINTF2("ALTER USER \"%s\" WITH PASSWORD '%s';\n",
+ effective_user, pwd1);
PG_CMD_CLOSE;
+ check_ok();
+
snprintf(pwdpath, sizeof(pwdpath), "%s/global/pg_pwd", pg_data);
if (stat(pwdpath, &statbuf) != 0 || !S_ISREG(statbuf.st_mode))
{
progname);
exit_nicely();
}
-
- check_ok();
}
/*
static void
unlimit_systables(void)
{
- char *systables_setup[] = {
+ PG_CMD_DECL;
+ char **line;
+ static char *systables_setup[] = {
"ALTER TABLE pg_attrdef CREATE TOAST TABLE;\n",
"ALTER TABLE pg_constraint CREATE TOAST TABLE;\n",
"ALTER TABLE pg_database CREATE TOAST TABLE;\n",
NULL
};
- PG_CMD_DECL;
-
fputs(_("enabling unlimited row size for system tables ... "), stdout);
fflush(stdout);
PG_CMD_OPEN;
for (line = systables_setup; *line != NULL; line++)
- PG_CMD_PUTLINE;
+ PG_CMD_PUTS(*line);
PG_CMD_CLOSE;
static void
setup_depend(void)
{
- char *pg_depend_setup[] = {
+ PG_CMD_DECL;
+ char **line;
+ static char *pg_depend_setup[] = {
/*
* Make PIN entries in pg_depend for all objects made so far in
* the tables that the dependency code handles. This is overkill
NULL
};
- PG_CMD_DECL;
-
fputs(_("initializing pg_depend ... "), stdout);
fflush(stdout);
PG_CMD_OPEN;
for (line = pg_depend_setup; *line != NULL; line++)
- PG_CMD_PUTLINE;
+ PG_CMD_PUTS(*line);
PG_CMD_CLOSE;
setup_sysviews(void)
{
PG_CMD_DECL;
-
+ char **line;
char **sysviews_setup;
fputs(_("creating system views ... "), stdout);
for (line = sysviews_setup; *line != NULL; line++)
{
- PG_CMD_PUTLINE;
+ PG_CMD_PUTS(*line);
free(*line);
}
static void
setup_description(void)
{
- PG_CMD_DECL_NOLINE;
- int fres;
+ PG_CMD_DECL;
fputs(_("loading pg_description ... "), stdout);
fflush(stdout);
PG_CMD_OPEN;
- fres = fprintf(pg,
- "CREATE TEMP TABLE tmp_pg_description ( "
- " objoid oid, "
- " classname name, "
- " objsubid int4, "
- " description text) WITHOUT OIDS;\n");
- if (fres < 0)
- exit_nicely();
+ PG_CMD_PUTS("CREATE TEMP TABLE tmp_pg_description ( "
+ " objoid oid, "
+ " classname name, "
+ " objsubid int4, "
+ " description text) WITHOUT OIDS;\n");
- fres = fprintf(pg,
- "COPY tmp_pg_description FROM '%s';\n",
+ PG_CMD_PRINTF1("COPY tmp_pg_description FROM '%s';\n",
desc_file);
- if (fres < 0)
- exit_nicely();
- fres = fprintf(pg,
- "INSERT INTO pg_description "
- " SELECT t.objoid, c.oid, t.objsubid, t.description "
- " FROM tmp_pg_description t, pg_class c "
- " WHERE c.relname = t.classname;\n");
- if (fres < 0)
- exit_nicely();
+ PG_CMD_PUTS("INSERT INTO pg_description "
+ " SELECT t.objoid, c.oid, t.objsubid, t.description "
+ " FROM tmp_pg_description t, pg_class c "
+ " WHERE c.relname = t.classname;\n");
PG_CMD_CLOSE;
setup_conversion(void)
{
PG_CMD_DECL;
-
+ char **line;
char **conv_lines;
fputs(_("creating conversions ... "), stdout);
for (line = conv_lines; *line != NULL; line++)
{
if (strstr(*line, "DROP CONVERSION") != *line)
- PG_CMD_PUTLINE;
-
+ PG_CMD_PUTS(*line);
free(*line);
}
static void
setup_privileges(void)
{
- char *privileges_setup[] = {
+ PG_CMD_DECL;
+ char **line;
+ char **priv_lines;
+ static char *privileges_setup[] = {
"UPDATE pg_class "
" SET relacl = '{\"=r/\\\\\"$POSTGRES_SUPERUSERNAME\\\\\"\"}' "
" WHERE relkind IN ('r', 'v', 'S') AND relacl IS NULL;\n",
NULL
};
- PG_CMD_DECL;
-
- char **priv_lines;
-
fputs(_("setting privileges on built-in objects ... "), stdout);
fflush(stdout);
priv_lines = replace_token(privileges_setup,
"$POSTGRES_SUPERUSERNAME", effective_user);
for (line = priv_lines; *line != NULL; line++)
- PG_CMD_PUTLINE;
+ PG_CMD_PUTS(*line);
PG_CMD_CLOSE;
setup_schema(void)
{
PG_CMD_DECL;
+ char **line;
char **lines;
- int fres;
fputs(_("creating information schema ... "), stdout);
fflush(stdout);
for (line = lines; *line != NULL; line++)
{
- PG_CMD_PUTLINE;
+ PG_CMD_PUTS(*line);
free(*line);
}
PG_CMD_OPEN;
- fres = fprintf(pg,
- "UPDATE information_schema.sql_implementation_info "
+ PG_CMD_PRINTF1("UPDATE information_schema.sql_implementation_info "
" SET character_value = '%s' "
" WHERE implementation_info_name = 'DBMS VERSION';\n",
infoversion);
- if (fres < 0)
- exit_nicely();
- fres = fprintf(pg,
- "COPY information_schema.sql_features "
+ PG_CMD_PRINTF1("COPY information_schema.sql_features "
" (feature_id, feature_name, sub_feature_id, "
" sub_feature_name, is_supported, comments) "
" FROM '%s';\n",
features_file);
- if (fres < 0)
- exit_nicely();
PG_CMD_CLOSE;
static void
vacuum_db(void)
{
- PG_CMD_DECL_NOLINE;
+ PG_CMD_DECL;
fputs(_("vacuuming database template1 ... "), stdout);
fflush(stdout);
PG_CMD_OPEN;
- if (fputs("ANALYZE;\nVACUUM FULL FREEZE;\n", pg) < 0)
- exit_nicely();
- fflush(pg);
+ PG_CMD_PUTS("ANALYZE;\nVACUUM FULL;\nVACUUM FREEZE;\n");
PG_CMD_CLOSE;
static void
make_template0(void)
{
- char *template0_setup[] = {
+ PG_CMD_DECL;
+ char **line;
+ static char *template0_setup[] = {
"CREATE DATABASE template0;\n",
"UPDATE pg_database SET "
" datistemplate = 't', "
NULL
};
- PG_CMD_DECL;
-
fputs(_("copying template1 to template0 ... "), stdout);
fflush(stdout);
PG_CMD_OPEN;
for (line = template0_setup; *line; line++)
- PG_CMD_PUTLINE;
+ PG_CMD_PUTS(*line);
PG_CMD_CLOSE;
if (caught_signal)
{
printf(_("caught signal\n"));
+ fflush(stdout);
exit_nicely();
}
else if (output_failed)
{
- printf(_("could not write to child process\n"));
+ printf(_("could not write to child process: %s\n"),
+ strerror(output_errno));
+ fflush(stdout);
exit_nicely();
}
else
{
/* all seems well */
printf(_("ok\n"));
+ fflush(stdout);
}
}
show_setting = true;
break;
default:
+ /* getopt_long already emitted a complaint */
fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
progname);
exit(1);
* local connections and are rejected in hba.c
*/
{
- fprintf(stderr, _("%s: unrecognized authentication method \"%s\"\n"), progname, authmethod);
+ fprintf(stderr, _("%s: unrecognized authentication method \"%s\"\n"),
+ progname, authmethod);
exit(1);
}