summaryrefslogtreecommitdiff
path: root/src/bin/psql
diff options
context:
space:
mode:
Diffstat (limited to 'src/bin/psql')
-rw-r--r--src/bin/psql/command.c94
-rw-r--r--src/bin/psql/help.c4
-rw-r--r--src/bin/psql/t/001_basic.pl7
-rw-r--r--src/bin/psql/tab-complete.in.c4
4 files changed, 105 insertions, 4 deletions
diff --git a/src/bin/psql/command.c b/src/bin/psql/command.c
index 0e00d73487c..cc602087db2 100644
--- a/src/bin/psql/command.c
+++ b/src/bin/psql/command.c
@@ -130,6 +130,8 @@ static backslashResult exec_command_pset(PsqlScanState scan_state, bool active_b
static backslashResult exec_command_quit(PsqlScanState scan_state, bool active_branch);
static backslashResult exec_command_reset(PsqlScanState scan_state, bool active_branch,
PQExpBuffer query_buf);
+static backslashResult exec_command_restrict(PsqlScanState scan_state, bool active_branch,
+ const char *cmd);
static backslashResult exec_command_s(PsqlScanState scan_state, bool active_branch);
static backslashResult exec_command_sendpipeline(PsqlScanState scan_state, bool active_branch);
static backslashResult exec_command_set(PsqlScanState scan_state, bool active_branch);
@@ -142,6 +144,8 @@ static backslashResult exec_command_syncpipeline(PsqlScanState scan_state, bool
static backslashResult exec_command_t(PsqlScanState scan_state, bool active_branch);
static backslashResult exec_command_T(PsqlScanState scan_state, bool active_branch);
static backslashResult exec_command_timing(PsqlScanState scan_state, bool active_branch);
+static backslashResult exec_command_unrestrict(PsqlScanState scan_state, bool active_branch,
+ const char *cmd);
static backslashResult exec_command_unset(PsqlScanState scan_state, bool active_branch,
const char *cmd);
static backslashResult exec_command_write(PsqlScanState scan_state, bool active_branch,
@@ -192,6 +196,8 @@ static char *pset_value_string(const char *param, printQueryOpt *popt);
static void checkWin32Codepage(void);
#endif
+static bool restricted;
+static char *restrict_key;
/*----------
@@ -237,8 +243,19 @@ HandleSlashCmds(PsqlScanState scan_state,
/* Parse off the command name */
cmd = psql_scan_slash_command(scan_state);
- /* And try to execute it */
- status = exec_command(cmd, scan_state, cstack, query_buf, previous_buf);
+ /*
+ * And try to execute it.
+ *
+ * If we are in "restricted" mode, the only allowable backslash command is
+ * \unrestrict (to exit restricted mode).
+ */
+ if (restricted && strcmp(cmd, "unrestrict") != 0)
+ {
+ pg_log_error("backslash commands are restricted; only \\unrestrict is allowed");
+ status = PSQL_CMD_ERROR;
+ }
+ else
+ status = exec_command(cmd, scan_state, cstack, query_buf, previous_buf);
if (status == PSQL_CMD_UNKNOWN)
{
@@ -416,6 +433,8 @@ exec_command(const char *cmd,
status = exec_command_quit(scan_state, active_branch);
else if (strcmp(cmd, "r") == 0 || strcmp(cmd, "reset") == 0)
status = exec_command_reset(scan_state, active_branch, query_buf);
+ else if (strcmp(cmd, "restrict") == 0)
+ status = exec_command_restrict(scan_state, active_branch, cmd);
else if (strcmp(cmd, "s") == 0)
status = exec_command_s(scan_state, active_branch);
else if (strcmp(cmd, "sendpipeline") == 0)
@@ -438,6 +457,8 @@ exec_command(const char *cmd,
status = exec_command_T(scan_state, active_branch);
else if (strcmp(cmd, "timing") == 0)
status = exec_command_timing(scan_state, active_branch);
+ else if (strcmp(cmd, "unrestrict") == 0)
+ status = exec_command_unrestrict(scan_state, active_branch, cmd);
else if (strcmp(cmd, "unset") == 0)
status = exec_command_unset(scan_state, active_branch, cmd);
else if (strcmp(cmd, "w") == 0 || strcmp(cmd, "write") == 0)
@@ -2755,6 +2776,35 @@ exec_command_reset(PsqlScanState scan_state, bool active_branch,
}
/*
+ * \restrict -- enter "restricted mode" with the provided key
+ */
+static backslashResult
+exec_command_restrict(PsqlScanState scan_state, bool active_branch,
+ const char *cmd)
+{
+ if (active_branch)
+ {
+ char *opt;
+
+ Assert(!restricted);
+
+ opt = psql_scan_slash_option(scan_state, OT_NORMAL, NULL, true);
+ if (opt == NULL || opt[0] == '\0')
+ {
+ pg_log_error("\\%s: missing required argument", cmd);
+ return PSQL_CMD_ERROR;
+ }
+
+ restrict_key = pstrdup(opt);
+ restricted = true;
+ }
+ else
+ ignore_slash_options(scan_state);
+
+ return PSQL_CMD_SKIP_LINE;
+}
+
+/*
* \s -- save history in a file or show it on the screen
*/
static backslashResult
@@ -3136,6 +3186,46 @@ exec_command_timing(PsqlScanState scan_state, bool active_branch)
}
/*
+ * \unrestrict -- exit "restricted mode" if provided key matches
+ */
+static backslashResult
+exec_command_unrestrict(PsqlScanState scan_state, bool active_branch,
+ const char *cmd)
+{
+ if (active_branch)
+ {
+ char *opt;
+
+ opt = psql_scan_slash_option(scan_state, OT_NORMAL, NULL, true);
+ if (opt == NULL || opt[0] == '\0')
+ {
+ pg_log_error("\\%s: missing required argument", cmd);
+ return PSQL_CMD_ERROR;
+ }
+
+ if (!restricted)
+ {
+ pg_log_error("\\%s: not currently in restricted mode", cmd);
+ return PSQL_CMD_ERROR;
+ }
+ else if (strcmp(opt, restrict_key) == 0)
+ {
+ pfree(restrict_key);
+ restricted = false;
+ }
+ else
+ {
+ pg_log_error("\\%s: wrong key", cmd);
+ return PSQL_CMD_ERROR;
+ }
+ }
+ else
+ ignore_slash_options(scan_state);
+
+ return PSQL_CMD_SKIP_LINE;
+}
+
+/*
* \unset -- unset variable
*/
static backslashResult
diff --git a/src/bin/psql/help.c b/src/bin/psql/help.c
index 8c62729a0d1..ed00c36695e 100644
--- a/src/bin/psql/help.c
+++ b/src/bin/psql/help.c
@@ -171,6 +171,10 @@ slashUsage(unsigned short int pager)
HELP0(" \\gset [PREFIX] execute query and store result in psql variables\n");
HELP0(" \\gx [(OPTIONS)] [FILE] as \\g, but forces expanded output mode\n");
HELP0(" \\q quit psql\n");
+ HELP0(" \\restrict RESTRICT_KEY\n"
+ " enter restricted mode with provided key\n");
+ HELP0(" \\unrestrict RESTRICT_KEY\n"
+ " exit restricted mode if key matches\n");
HELP0(" \\watch [[i=]SEC] [c=N] [m=MIN]\n"
" execute query every SEC seconds, up to N times,\n"
" stop if less than MIN rows are returned\n");
diff --git a/src/bin/psql/t/001_basic.pl b/src/bin/psql/t/001_basic.pl
index f42c3961e09..cf07a9dbd5e 100644
--- a/src/bin/psql/t/001_basic.pl
+++ b/src/bin/psql/t/001_basic.pl
@@ -530,4 +530,11 @@ psql_fails_like(
qr/COPY in a pipeline is not supported, aborting connection/,
'\copy to in pipeline: fails');
+psql_fails_like(
+ $node,
+ qq{\\restrict test
+\\! should_fail},
+ qr/backslash commands are restricted; only \\unrestrict is allowed/,
+ 'meta-command in restrict mode fails');
+
done_testing();
diff --git a/src/bin/psql/tab-complete.in.c b/src/bin/psql/tab-complete.in.c
index 1f2ca946fc5..8b10f2313f3 100644
--- a/src/bin/psql/tab-complete.in.c
+++ b/src/bin/psql/tab-complete.in.c
@@ -1918,11 +1918,11 @@ psql_completion(const char *text, int start, int end)
"\\out",
"\\parse", "\\password", "\\print", "\\prompt", "\\pset",
"\\qecho", "\\quit",
- "\\reset",
+ "\\reset", "\\restrict",
"\\s", "\\sendpipeline", "\\set", "\\setenv", "\\sf",
"\\startpipeline", "\\sv", "\\syncpipeline",
"\\t", "\\T", "\\timing",
- "\\unset",
+ "\\unrestrict", "\\unset",
"\\x",
"\\warn", "\\watch", "\\write",
"\\z",