diff --git a/src/backend/main/main.c b/src/backend/main/main.c
index a8ab4c4ab6f64056e64682aa2d19e7c29ef933a0..1b9cbd1de360816aea194b601c0442a60be2514c 100644
--- a/src/backend/main/main.c
+++ b/src/backend/main/main.c
@@ -58,6 +58,8 @@ static void check_root(const char *progname);
 int
 main(int argc, char *argv[])
 {
+	bool		do_check_root = true;
+
 	progname = get_progname(argv[0]);
 
 	/*
@@ -151,7 +153,8 @@ main(int argc, char *argv[])
 	unsetenv("LC_ALL");
 
 	/*
-	 * Catch standard options before doing much else
+	 * Catch standard options before doing much else, in particular before we
+	 * insist on not being root.
 	 */
 	if (argc > 1)
 	{
@@ -165,12 +168,29 @@ main(int argc, char *argv[])
 			puts("postgres (PostgreSQL) " PG_VERSION);
 			exit(0);
 		}
+
+		/*
+		 * In addition to the above, we allow "--describe-config" and "-C var"
+		 * to be called by root.  This is reasonably safe since these are
+		 * read-only activities.  The -C case is important because pg_ctl may
+		 * try to invoke it while still holding administrator privileges on
+		 * Windows.  Note that while -C can normally be in any argv position,
+		 * if you wanna bypass the root check you gotta put it first.  This
+		 * reduces the risk that we might misinterpret some other mode's -C
+		 * switch as being the postmaster/postgres one.
+		 */
+		if (strcmp(argv[1], "--describe-config") == 0)
+			do_check_root = false;
+		else if (argc > 2 && strcmp(argv[1], "-C") == 0)
+			do_check_root = false;
 	}
 
 	/*
-	 * Make sure we are not running as root.
+	 * Make sure we are not running as root, unless it's safe for the selected
+	 * option.
 	 */
-	check_root(progname);
+	if (do_check_root)
+		check_root(progname);
 
 	/*
 	 * Dispatch to one of various subprograms depending on first argument.
diff --git a/src/bin/pg_ctl/pg_ctl.c b/src/bin/pg_ctl/pg_ctl.c
index 1f921819c23563bc9068fb1bab83ba2bec61627d..fc87e7d76ed166af23cf83fa91991211605af409 100644
--- a/src/bin/pg_ctl/pg_ctl.c
+++ b/src/bin/pg_ctl/pg_ctl.c
@@ -2034,9 +2034,11 @@ adjust_data_dir(void)
 	else
 		my_exec_path = pg_strdup(exec_path);
 
-	snprintf(cmd, MAXPGPATH, SYSTEMQUOTE "\"%s\" %s%s -C data_directory" SYSTEMQUOTE,
-			 my_exec_path, pgdata_opt ? pgdata_opt : "", post_opts ?
-			 post_opts : "");
+	/* it's important for -C to be the first option, see main.c */
+	snprintf(cmd, MAXPGPATH, SYSTEMQUOTE "\"%s\" -C data_directory %s%s" 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)