aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/backend/bootstrap/bootstrap.c15
-rw-r--r--src/backend/main/main.c86
-rw-r--r--src/backend/postmaster/postmaster.c15
-rw-r--r--src/backend/tcop/postgres.c15
-rw-r--r--src/include/postmaster/postmaster.h17
-rw-r--r--src/tools/pgindent/typedefs.list1
6 files changed, 133 insertions, 16 deletions
diff --git a/src/backend/bootstrap/bootstrap.c b/src/backend/bootstrap/bootstrap.c
index d31a67599c9..a5217773ffc 100644
--- a/src/backend/bootstrap/bootstrap.c
+++ b/src/backend/bootstrap/bootstrap.c
@@ -224,8 +224,21 @@ BootstrapModeMain(int argc, char *argv[], bool check_only)
case 'B':
SetConfigOption("shared_buffers", optarg, PGC_POSTMASTER, PGC_S_ARGV);
break;
- case 'c':
case '-':
+
+ /*
+ * Error if the user misplaced a special must-be-first option
+ * for dispatching to a subprogram. parse_dispatch_option()
+ * returns DISPATCH_POSTMASTER if it doesn't find a match, so
+ * error for anything else.
+ */
+ if (parse_dispatch_option(optarg) != DISPATCH_POSTMASTER)
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("--%s must be first argument", optarg)));
+
+ /* FALLTHROUGH */
+ case 'c':
{
char *name,
*value;
diff --git a/src/backend/main/main.c b/src/backend/main/main.c
index aea93a02298..3acb46bd464 100644
--- a/src/backend/main/main.c
+++ b/src/backend/main/main.c
@@ -43,6 +43,19 @@
const char *progname;
static bool reached_main = false;
+/* names of special must-be-first options for dispatching to subprograms */
+static const char *const DispatchOptionNames[] =
+{
+ [DISPATCH_CHECK] = "check",
+ [DISPATCH_BOOT] = "boot",
+ [DISPATCH_FORKCHILD] = "forkchild",
+ [DISPATCH_DESCRIBE_CONFIG] = "describe-config",
+ [DISPATCH_SINGLE] = "single",
+ /* DISPATCH_POSTMASTER has no name */
+};
+
+StaticAssertDecl(lengthof(DispatchOptionNames) == DISPATCH_POSTMASTER,
+ "array length mismatch");
static void startup_hacks(const char *progname);
static void init_locale(const char *categoryname, int category, const char *locale);
@@ -57,6 +70,7 @@ int
main(int argc, char *argv[])
{
bool do_check_root = true;
+ DispatchOption dispatch_option = DISPATCH_POSTMASTER;
reached_main = true;
@@ -179,26 +193,72 @@ main(int argc, char *argv[])
* Dispatch to one of various subprograms depending on first argument.
*/
- if (argc > 1 && strcmp(argv[1], "--check") == 0)
- BootstrapModeMain(argc, argv, true);
- else if (argc > 1 && strcmp(argv[1], "--boot") == 0)
- BootstrapModeMain(argc, argv, false);
+ if (argc > 1 && argv[1][0] == '-' && argv[1][1] == '-')
+ dispatch_option = parse_dispatch_option(&argv[1][2]);
+
+ switch (dispatch_option)
+ {
+ case DISPATCH_CHECK:
+ BootstrapModeMain(argc, argv, true);
+ break;
+ case DISPATCH_BOOT:
+ BootstrapModeMain(argc, argv, false);
+ break;
+ case DISPATCH_FORKCHILD:
#ifdef EXEC_BACKEND
- else if (argc > 1 && strncmp(argv[1], "--forkchild", 11) == 0)
- SubPostmasterMain(argc, argv);
+ SubPostmasterMain(argc, argv);
+#else
+ Assert(false); /* should never happen */
#endif
- else if (argc > 1 && strcmp(argv[1], "--describe-config") == 0)
- GucInfoMain();
- else if (argc > 1 && strcmp(argv[1], "--single") == 0)
- PostgresSingleUserMain(argc, argv,
- strdup(get_user_name_or_exit(progname)));
- else
- PostmasterMain(argc, argv);
+ break;
+ case DISPATCH_DESCRIBE_CONFIG:
+ GucInfoMain();
+ break;
+ case DISPATCH_SINGLE:
+ PostgresSingleUserMain(argc, argv,
+ strdup(get_user_name_or_exit(progname)));
+ break;
+ case DISPATCH_POSTMASTER:
+ PostmasterMain(argc, argv);
+ break;
+ }
+
/* the functions above should not return */
abort();
}
+/*
+ * Returns the matching DispatchOption value for the given option name. If no
+ * match is found, DISPATCH_POSTMASTER is returned.
+ */
+DispatchOption
+parse_dispatch_option(const char *name)
+{
+ for (int i = 0; i < lengthof(DispatchOptionNames); i++)
+ {
+ /*
+ * Unlike the other dispatch options, "forkchild" takes an argument,
+ * so we just look for the prefix for that one. For non-EXEC_BACKEND
+ * builds, we never want to return DISPATCH_FORKCHILD, so skip over it
+ * in that case.
+ */
+ if (i == DISPATCH_FORKCHILD)
+ {
+#ifdef EXEC_BACKEND
+ if (strncmp(DispatchOptionNames[DISPATCH_FORKCHILD], name,
+ strlen(DispatchOptionNames[DISPATCH_FORKCHILD])) == 0)
+ return DISPATCH_FORKCHILD;
+#endif
+ continue;
+ }
+
+ if (strcmp(DispatchOptionNames[i], name) == 0)
+ return (DispatchOption) i;
+ }
+ /* no match means this is a postmaster */
+ return DISPATCH_POSTMASTER;
+}
/*
* Place platform-specific startup hacks here. This is the right
diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c
index 6376d430870..ce00f4032ee 100644
--- a/src/backend/postmaster/postmaster.c
+++ b/src/backend/postmaster/postmaster.c
@@ -589,8 +589,21 @@ PostmasterMain(int argc, char *argv[])
output_config_variable = strdup(optarg);
break;
- case 'c':
case '-':
+
+ /*
+ * Error if the user misplaced a special must-be-first option
+ * for dispatching to a subprogram. parse_dispatch_option()
+ * returns DISPATCH_POSTMASTER if it doesn't find a match, so
+ * error for anything else.
+ */
+ if (parse_dispatch_option(optarg) != DISPATCH_POSTMASTER)
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("--%s must be first argument", optarg)));
+
+ /* FALLTHROUGH */
+ case 'c':
{
char *name,
*value;
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 4b985bd0561..42af7680456 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -3947,8 +3947,21 @@ process_postgres_switches(int argc, char *argv[], GucContext ctx,
/* ignored for consistency with the postmaster */
break;
- case 'c':
case '-':
+
+ /*
+ * Error if the user misplaced a special must-be-first option
+ * for dispatching to a subprogram. parse_dispatch_option()
+ * returns DISPATCH_POSTMASTER if it doesn't find a match, so
+ * error for anything else.
+ */
+ if (parse_dispatch_option(optarg) != DISPATCH_POSTMASTER)
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("--%s must be first argument", optarg)));
+
+ /* FALLTHROUGH */
+ case 'c':
{
char *name,
*value;
diff --git a/src/include/postmaster/postmaster.h b/src/include/postmaster/postmaster.h
index f05eb1c470b..24d49a5439e 100644
--- a/src/include/postmaster/postmaster.h
+++ b/src/include/postmaster/postmaster.h
@@ -138,4 +138,21 @@ extern PMChild *FindPostmasterChildByPid(int pid);
*/
#define MAX_BACKENDS 0x3FFFF
+/*
+ * These values correspond to the special must-be-first options for dispatching
+ * to various subprograms. parse_dispatch_option() can be used to convert an
+ * option name to one of these values.
+ */
+typedef enum DispatchOption
+{
+ DISPATCH_CHECK,
+ DISPATCH_BOOT,
+ DISPATCH_FORKCHILD,
+ DISPATCH_DESCRIBE_CONFIG,
+ DISPATCH_SINGLE,
+ DISPATCH_POSTMASTER, /* must be last */
+} DispatchOption;
+
+extern DispatchOption parse_dispatch_option(const char *name);
+
#endif /* _POSTMASTER_H */
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 2d4c870423a..ce33e55bf1d 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -619,6 +619,7 @@ DirectoryMethodFile
DisableTimeoutParams
DiscardMode
DiscardStmt
+DispatchOption
DistanceValue
DistinctExpr
DoState