From aaa6e1def292cdacb6b27088898793b1b879fedf Mon Sep 17 00:00:00 2001 From: Bruce Momjian Date: Thu, 6 Oct 2011 09:38:39 -0400 Subject: [PATCH] Add postmaster -C option to query configuration parameters, and have pg_ctl use that to query the data directory for config-only installs. This fixes awkward or impossible pg_ctl operation for config-only installs. --- doc/src/sgml/ref/postgres-ref.sgml | 14 ++++++ src/backend/main/main.c | 1 + src/backend/postmaster/postmaster.c | 15 +++++- src/backend/tcop/postgres.c | 8 +++- src/bin/pg_ctl/pg_ctl.c | 72 ++++++++++++++++++++++++++--- 5 files changed, 100 insertions(+), 10 deletions(-) diff --git a/doc/src/sgml/ref/postgres-ref.sgml b/doc/src/sgml/ref/postgres-ref.sgml index b16bbdfa4b..3807f4090a 100644 --- a/doc/src/sgml/ref/postgres-ref.sgml +++ b/doc/src/sgml/ref/postgres-ref.sgml @@ -140,6 +140,20 @@ PostgreSQL documentation + + + + + Returns the value of a named run-time parameter, and exits. + (See the + + + diff --git a/src/backend/main/main.c b/src/backend/main/main.c index 8d9cb9428d..b14c7318ab 100644 --- a/src/backend/main/main.c +++ b/src/backend/main/main.c @@ -283,6 +283,7 @@ help(const char *progname) #endif printf(_(" -B NBUFFERS number of shared buffers\n")); printf(_(" -c NAME=VALUE set run-time parameter\n")); + printf(_(" -C NAME return run-time parameter\n")); printf(_(" -d 1-5 debugging level\n")); printf(_(" -D DATADIR database directory\n")); printf(_(" -e use European date input format (DMY)\n")); diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c index 0a84d97f51..dd7493cf9d 100644 --- a/src/backend/postmaster/postmaster.c +++ b/src/backend/postmaster/postmaster.c @@ -203,6 +203,8 @@ bool enable_bonjour = false; char *bonjour_name; bool restart_after_crash = true; +char *output_config_variable = NULL; + /* PIDs of special child processes; 0 when not running */ static pid_t StartupPID = 0, BgWriterPID = 0, @@ -537,7 +539,7 @@ PostmasterMain(int argc, char *argv[]) * tcop/postgres.c (the option sets should not conflict) and with the * common help() function in main/main.c. */ - while ((opt = getopt(argc, argv, "A:B:bc:D:d:EeFf:h:ijk:lN:nOo:Pp:r:S:sTt:W:-:")) != -1) + while ((opt = getopt(argc, argv, "A:B:bc:C:D:d:EeFf:h:ijk:lN:nOo:Pp:r:S:sTt:W:-:")) != -1) { switch (opt) { @@ -554,6 +556,10 @@ PostmasterMain(int argc, char *argv[]) IsBinaryUpgrade = true; break; + case 'C': + output_config_variable = optarg; + break; + case 'D': userDoption = optarg; break; @@ -728,6 +734,13 @@ PostmasterMain(int argc, char *argv[]) if (!SelectConfigFiles(userDoption, progname)) ExitPostmaster(2); + if (output_config_variable != NULL) + { + /* permission is handled because the user is reading inside the data dir */ + puts(GetConfigOption(output_config_variable, false, false)); + ExitPostmaster(0); + } + /* Verify that DataDir looks reasonable */ checkDataDir(); diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c index c7eac71e91..19d94b252c 100644 --- a/src/backend/tcop/postgres.c +++ b/src/backend/tcop/postgres.c @@ -3170,7 +3170,7 @@ process_postgres_switches(int argc, char *argv[], GucContext ctx) * postmaster/postmaster.c (the option sets should not conflict) and with * the common help() function in main/main.c. */ - while ((flag = getopt(argc, argv, "A:B:bc:D:d:EeFf:h:ijk:lN:nOo:Pp:r:S:sTt:v:W:-:")) != -1) + while ((flag = getopt(argc, argv, "A:B:bc:C:D:d:EeFf:h:ijk:lN:nOo:Pp:r:S:sTt:v:W:-:")) != -1) { switch (flag) { @@ -3187,6 +3187,10 @@ process_postgres_switches(int argc, char *argv[], GucContext ctx) IsBinaryUpgrade = true; break; + case 'C': + /* ignored for consistency with the postmaster */ + break; + case 'D': if (secure) userDoption = strdup(optarg); @@ -3272,7 +3276,7 @@ process_postgres_switches(int argc, char *argv[], GucContext ctx) break; case 'T': - /* ignored for consistency with postmaster */ + /* ignored for consistency with the postmaster */ break; case 't': diff --git a/src/bin/pg_ctl/pg_ctl.c b/src/bin/pg_ctl/pg_ctl.c index 0dbdfe7312..e633d0c18f 100644 --- a/src/bin/pg_ctl/pg_ctl.c +++ b/src/bin/pg_ctl/pg_ctl.c @@ -81,6 +81,7 @@ static ShutdownMode shutdown_mode = SMART_MODE; static int sig = SIGTERM; /* default */ static CtlCommand ctl_command = NO_COMMAND; static char *pg_data = NULL; +static char *pg_config = NULL; static char *pgdata_opt = NULL; static char *post_opts = NULL; static const char *progname; @@ -131,6 +132,7 @@ static void do_status(void); static void do_promote(void); static void do_kill(pgpid_t pid); static void print_msg(const char *msg); +static void adjust_data_dir(void); #if defined(WIN32) || defined(__CYGWIN__) static bool pgwin32_IsInstalled(SC_HANDLE); @@ -1265,10 +1267,10 @@ pgwin32_CommandLine(bool registration) strcat(cmdLine, "\""); } - if (pg_data) + if (pg_config) { strcat(cmdLine, " -D \""); - strcat(cmdLine, pg_data); + strcat(cmdLine, pg_config); strcat(cmdLine, "\""); } @@ -1886,6 +1888,59 @@ set_starttype(char *starttypeopt) } #endif +/* + * adjust_data_dir + * + * If a configuration-only directory was specified, find the real data dir. + */ +void +adjust_data_dir(void) +{ + char cmd[MAXPGPATH], filename[MAXPGPATH], *my_exec_path; + FILE *fd; + + /* If there is no postgresql.conf, it can't be a config-only dir */ + snprintf(filename, sizeof(filename), "%s/postgresql.conf", pg_config); + if ((fd = fopen(filename, "r")) == NULL) + return; + fclose(fd); + + /* If PG_VERSION exists, it can't be a config-only dir */ + snprintf(filename, sizeof(filename), "%s/PG_VERSION", pg_config); + if ((fd = fopen(filename, "r")) != NULL) + { + fclose(fd); + return; + } + + /* Must be a configuration directory, so find the data directory */ + + /* we use a private my_exec_path to avoid interfering with later uses */ + if (exec_path == NULL) + my_exec_path = find_other_exec_or_die(argv0, "postgres", PG_BACKEND_VERSIONSTR); + else + my_exec_path = xstrdup(exec_path); + + snprintf(cmd, MAXPGPATH, SYSTEMQUOTE "\"%s\" %s%s -C data_directory" SYSTEMQUOTE, + my_exec_path, pgdata_opt ? pgdata_opt : "", post_opts ? + post_opts : ""); + + fd = popen(cmd, "r"); + if (fd == NULL || fgets(filename, sizeof(filename), fd) == NULL) + { + write_stderr(_("%s: cannot find the data directory using %s\n"), progname, my_exec_path); + exit(1); + } + pclose(fd); + free(my_exec_path); + + if (strlen(filename) > 0 && filename[strlen(filename) - 1] == '\n') + filename[strlen(filename) - 1] = '\0'; + free(pg_data); + pg_data = xstrdup(filename); + canonicalize_path(pg_data); +} + int main(int argc, char **argv) @@ -2120,14 +2175,17 @@ main(int argc, char **argv) } /* Note we put any -D switch into the env var above */ - pg_data = getenv("PGDATA"); - if (pg_data) + pg_config = getenv("PGDATA"); + if (pg_config) { - pg_data = xstrdup(pg_data); - canonicalize_path(pg_data); + pg_config = xstrdup(pg_config); + canonicalize_path(pg_config); + pg_data = xstrdup(pg_config); } - if (pg_data == NULL && + adjust_data_dir(); + + if (pg_config == NULL && ctl_command != KILL_COMMAND && ctl_command != UNREGISTER_COMMAND) { write_stderr(_("%s: no database directory specified and environment variable PGDATA unset\n"), -- 2.40.0