1 /*
2  * psql - the PostgreSQL interactive terminal
3  *
4  * Copyright (c) 2000-2019, PostgreSQL Global Development Group
5  *
6  * src/bin/psql/command.c
7  */
8 #include "postgres_fe.h"
9 #include "command.h"
10 
11 #include <ctype.h>
12 #include <time.h>
13 #include <pwd.h>
14 #include <utime.h>
15 #ifndef WIN32
16 #include <sys/stat.h>			/* for stat() */
17 #include <fcntl.h>				/* open() flags */
18 #include <unistd.h>				/* for geteuid(), getpid(), stat() */
19 #else
20 #include <win32.h>
21 #include <io.h>
22 #include <fcntl.h>
23 #include <direct.h>
24 #include <sys/stat.h>			/* for stat() */
25 #endif
26 
27 #include "catalog/pg_class_d.h"
28 #include "portability/instr_time.h"
29 
30 #include "libpq-fe.h"
31 #include "pqexpbuffer.h"
32 #include "common/logging.h"
33 #include "fe_utils/print.h"
34 #include "fe_utils/string_utils.h"
35 
36 #include "common.h"
37 #include "copy.h"
38 #include "crosstabview.h"
39 #include "describe.h"
40 #include "help.h"
41 #include "input.h"
42 #include "large_obj.h"
43 #include "mainloop.h"
44 #include "psqlscanslash.h"
45 #include "settings.h"
46 #include "variables.h"
47 
48 /*
49  * Editable database object types.
50  */
51 typedef enum EditableObjectType
52 {
53 	EditableFunction,
54 	EditableView
55 } EditableObjectType;
56 
57 /* local function declarations */
58 static backslashResult exec_command(const char *cmd,
59 									PsqlScanState scan_state,
60 									ConditionalStack cstack,
61 									PQExpBuffer query_buf,
62 									PQExpBuffer previous_buf);
63 static backslashResult exec_command_a(PsqlScanState scan_state, bool active_branch);
64 static backslashResult exec_command_C(PsqlScanState scan_state, bool active_branch);
65 static backslashResult exec_command_connect(PsqlScanState scan_state, bool active_branch);
66 static backslashResult exec_command_cd(PsqlScanState scan_state, bool active_branch,
67 									   const char *cmd);
68 static backslashResult exec_command_conninfo(PsqlScanState scan_state, bool active_branch);
69 static backslashResult exec_command_copy(PsqlScanState scan_state, bool active_branch);
70 static backslashResult exec_command_copyright(PsqlScanState scan_state, bool active_branch);
71 static backslashResult exec_command_crosstabview(PsqlScanState scan_state, bool active_branch);
72 static backslashResult exec_command_d(PsqlScanState scan_state, bool active_branch,
73 									  const char *cmd);
74 static backslashResult exec_command_edit(PsqlScanState scan_state, bool active_branch,
75 										 PQExpBuffer query_buf, PQExpBuffer previous_buf);
76 static backslashResult exec_command_ef_ev(PsqlScanState scan_state, bool active_branch,
77 										  PQExpBuffer query_buf, bool is_func);
78 static backslashResult exec_command_echo(PsqlScanState scan_state, bool active_branch,
79 										 const char *cmd);
80 static backslashResult exec_command_elif(PsqlScanState scan_state, ConditionalStack cstack,
81 										 PQExpBuffer query_buf);
82 static backslashResult exec_command_else(PsqlScanState scan_state, ConditionalStack cstack,
83 										 PQExpBuffer query_buf);
84 static backslashResult exec_command_endif(PsqlScanState scan_state, ConditionalStack cstack,
85 										  PQExpBuffer query_buf);
86 static backslashResult exec_command_encoding(PsqlScanState scan_state, bool active_branch);
87 static backslashResult exec_command_errverbose(PsqlScanState scan_state, bool active_branch);
88 static backslashResult exec_command_f(PsqlScanState scan_state, bool active_branch);
89 static backslashResult exec_command_g(PsqlScanState scan_state, bool active_branch,
90 									  const char *cmd);
91 static backslashResult exec_command_gdesc(PsqlScanState scan_state, bool active_branch);
92 static backslashResult exec_command_gexec(PsqlScanState scan_state, bool active_branch);
93 static backslashResult exec_command_gset(PsqlScanState scan_state, bool active_branch);
94 static backslashResult exec_command_help(PsqlScanState scan_state, bool active_branch);
95 static backslashResult exec_command_html(PsqlScanState scan_state, bool active_branch);
96 static backslashResult exec_command_include(PsqlScanState scan_state, bool active_branch,
97 											const char *cmd);
98 static backslashResult exec_command_if(PsqlScanState scan_state, ConditionalStack cstack,
99 									   PQExpBuffer query_buf);
100 static backslashResult exec_command_list(PsqlScanState scan_state, bool active_branch,
101 										 const char *cmd);
102 static backslashResult exec_command_lo(PsqlScanState scan_state, bool active_branch,
103 									   const char *cmd);
104 static backslashResult exec_command_out(PsqlScanState scan_state, bool active_branch);
105 static backslashResult exec_command_print(PsqlScanState scan_state, bool active_branch,
106 										  PQExpBuffer query_buf, PQExpBuffer previous_buf);
107 static backslashResult exec_command_password(PsqlScanState scan_state, bool active_branch);
108 static backslashResult exec_command_prompt(PsqlScanState scan_state, bool active_branch,
109 										   const char *cmd);
110 static backslashResult exec_command_pset(PsqlScanState scan_state, bool active_branch);
111 static backslashResult exec_command_quit(PsqlScanState scan_state, bool active_branch);
112 static backslashResult exec_command_reset(PsqlScanState scan_state, bool active_branch,
113 										  PQExpBuffer query_buf);
114 static backslashResult exec_command_s(PsqlScanState scan_state, bool active_branch);
115 static backslashResult exec_command_set(PsqlScanState scan_state, bool active_branch);
116 static backslashResult exec_command_setenv(PsqlScanState scan_state, bool active_branch,
117 										   const char *cmd);
118 static backslashResult exec_command_sf_sv(PsqlScanState scan_state, bool active_branch,
119 										  const char *cmd, bool is_func);
120 static backslashResult exec_command_t(PsqlScanState scan_state, bool active_branch);
121 static backslashResult exec_command_T(PsqlScanState scan_state, bool active_branch);
122 static backslashResult exec_command_timing(PsqlScanState scan_state, bool active_branch);
123 static backslashResult exec_command_unset(PsqlScanState scan_state, bool active_branch,
124 										  const char *cmd);
125 static backslashResult exec_command_write(PsqlScanState scan_state, bool active_branch,
126 										  const char *cmd,
127 										  PQExpBuffer query_buf, PQExpBuffer previous_buf);
128 static backslashResult exec_command_watch(PsqlScanState scan_state, bool active_branch,
129 										  PQExpBuffer query_buf, PQExpBuffer previous_buf);
130 static backslashResult exec_command_x(PsqlScanState scan_state, bool active_branch);
131 static backslashResult exec_command_z(PsqlScanState scan_state, bool active_branch);
132 static backslashResult exec_command_shell_escape(PsqlScanState scan_state, bool active_branch);
133 static backslashResult exec_command_slash_command_help(PsqlScanState scan_state, bool active_branch);
134 static char *read_connect_arg(PsqlScanState scan_state);
135 static PQExpBuffer gather_boolean_expression(PsqlScanState scan_state);
136 static bool is_true_boolean_expression(PsqlScanState scan_state, const char *name);
137 static void ignore_boolean_expression(PsqlScanState scan_state);
138 static void ignore_slash_options(PsqlScanState scan_state);
139 static void ignore_slash_filepipe(PsqlScanState scan_state);
140 static void ignore_slash_whole_line(PsqlScanState scan_state);
141 static bool is_branching_command(const char *cmd);
142 static void save_query_text_state(PsqlScanState scan_state, ConditionalStack cstack,
143 								  PQExpBuffer query_buf);
144 static void discard_query_text(PsqlScanState scan_state, ConditionalStack cstack,
145 							   PQExpBuffer query_buf);
146 static void copy_previous_query(PQExpBuffer query_buf, PQExpBuffer previous_buf);
147 static bool do_connect(enum trivalue reuse_previous_specification,
148 					   char *dbname, char *user, char *host, char *port);
149 static bool do_edit(const char *filename_arg, PQExpBuffer query_buf,
150 					int lineno, bool *edited);
151 static bool do_shell(const char *command);
152 static bool do_watch(PQExpBuffer query_buf, double sleep);
153 static bool lookup_object_oid(EditableObjectType obj_type, const char *desc,
154 							  Oid *obj_oid);
155 static bool get_create_object_cmd(EditableObjectType obj_type, Oid oid,
156 								  PQExpBuffer buf);
157 static int	strip_lineno_from_objdesc(char *obj);
158 static int	count_lines_in_buf(PQExpBuffer buf);
159 static void print_with_linenumbers(FILE *output, char *lines,
160 								   const char *header_keyword);
161 static void minimal_error_message(PGresult *res);
162 
163 static void printSSLInfo(void);
164 static void printGSSInfo(void);
165 static bool printPsetInfo(const char *param, struct printQueryOpt *popt);
166 static char *pset_value_string(const char *param, struct printQueryOpt *popt);
167 
168 #ifdef WIN32
169 static void checkWin32Codepage(void);
170 #endif
171 
172 
173 
174 /*----------
175  * HandleSlashCmds:
176  *
177  * Handles all the different commands that start with '\'.
178  * Ordinarily called by MainLoop().
179  *
180  * scan_state is a lexer working state that is set to continue scanning
181  * just after the '\'.  The lexer is advanced past the command and all
182  * arguments on return.
183  *
184  * cstack is the current \if stack state.  This will be examined, and
185  * possibly modified by conditional commands.
186  *
187  * query_buf contains the query-so-far, which may be modified by
188  * execution of the backslash command (for example, \r clears it).
189  *
190  * previous_buf contains the query most recently sent to the server
191  * (empty if none yet).  This should not be modified here, but some
192  * commands copy its content into query_buf.
193  *
194  * query_buf and previous_buf will be NULL when executing a "-c"
195  * command-line option.
196  *
197  * Returns a status code indicating what action is desired, see command.h.
198  *----------
199  */
200 
201 backslashResult
HandleSlashCmds(PsqlScanState scan_state,ConditionalStack cstack,PQExpBuffer query_buf,PQExpBuffer previous_buf)202 HandleSlashCmds(PsqlScanState scan_state,
203 				ConditionalStack cstack,
204 				PQExpBuffer query_buf,
205 				PQExpBuffer previous_buf)
206 {
207 	backslashResult status;
208 	char	   *cmd;
209 	char	   *arg;
210 
211 	Assert(scan_state != NULL);
212 	Assert(cstack != NULL);
213 
214 	/* Parse off the command name */
215 	cmd = psql_scan_slash_command(scan_state);
216 
217 	/* And try to execute it */
218 	status = exec_command(cmd, scan_state, cstack, query_buf, previous_buf);
219 
220 	if (status == PSQL_CMD_UNKNOWN)
221 	{
222 		pg_log_error("invalid command \\%s", cmd);
223 		if (pset.cur_cmd_interactive)
224 			pg_log_info("Try \\? for help.");
225 		status = PSQL_CMD_ERROR;
226 	}
227 
228 	if (status != PSQL_CMD_ERROR)
229 	{
230 		/*
231 		 * Eat any remaining arguments after a valid command.  We want to
232 		 * suppress evaluation of backticks in this situation, so transiently
233 		 * push an inactive conditional-stack entry.
234 		 */
235 		bool		active_branch = conditional_active(cstack);
236 
237 		conditional_stack_push(cstack, IFSTATE_IGNORED);
238 		while ((arg = psql_scan_slash_option(scan_state,
239 											 OT_NORMAL, NULL, false)))
240 		{
241 			if (active_branch)
242 				pg_log_warning("\\%s: extra argument \"%s\" ignored", cmd, arg);
243 			free(arg);
244 		}
245 		conditional_stack_pop(cstack);
246 	}
247 	else
248 	{
249 		/* silently throw away rest of line after an erroneous command */
250 		while ((arg = psql_scan_slash_option(scan_state,
251 											 OT_WHOLE_LINE, NULL, false)))
252 			free(arg);
253 	}
254 
255 	/* if there is a trailing \\, swallow it */
256 	psql_scan_slash_command_end(scan_state);
257 
258 	free(cmd);
259 
260 	/* some commands write to queryFout, so make sure output is sent */
261 	fflush(pset.queryFout);
262 
263 	return status;
264 }
265 
266 
267 /*
268  * Subroutine to actually try to execute a backslash command.
269  *
270  * The typical "success" result code is PSQL_CMD_SKIP_LINE, although some
271  * commands return something else.  Failure results are PSQL_CMD_ERROR,
272  * unless PSQL_CMD_UNKNOWN is more appropriate.
273  */
274 static backslashResult
exec_command(const char * cmd,PsqlScanState scan_state,ConditionalStack cstack,PQExpBuffer query_buf,PQExpBuffer previous_buf)275 exec_command(const char *cmd,
276 			 PsqlScanState scan_state,
277 			 ConditionalStack cstack,
278 			 PQExpBuffer query_buf,
279 			 PQExpBuffer previous_buf)
280 {
281 	backslashResult status;
282 	bool		active_branch = conditional_active(cstack);
283 
284 	/*
285 	 * In interactive mode, warn when we're ignoring a command within a false
286 	 * \if-branch.  But we continue on, so as to parse and discard the right
287 	 * amount of parameter text.  Each individual backslash command subroutine
288 	 * is responsible for doing nothing after discarding appropriate
289 	 * arguments, if !active_branch.
290 	 */
291 	if (pset.cur_cmd_interactive && !active_branch &&
292 		!is_branching_command(cmd))
293 	{
294 		pg_log_warning("\\%s command ignored; use \\endif or Ctrl-C to exit current \\if block",
295 					   cmd);
296 	}
297 
298 	if (strcmp(cmd, "a") == 0)
299 		status = exec_command_a(scan_state, active_branch);
300 	else if (strcmp(cmd, "C") == 0)
301 		status = exec_command_C(scan_state, active_branch);
302 	else if (strcmp(cmd, "c") == 0 || strcmp(cmd, "connect") == 0)
303 		status = exec_command_connect(scan_state, active_branch);
304 	else if (strcmp(cmd, "cd") == 0)
305 		status = exec_command_cd(scan_state, active_branch, cmd);
306 	else if (strcmp(cmd, "conninfo") == 0)
307 		status = exec_command_conninfo(scan_state, active_branch);
308 	else if (pg_strcasecmp(cmd, "copy") == 0)
309 		status = exec_command_copy(scan_state, active_branch);
310 	else if (strcmp(cmd, "copyright") == 0)
311 		status = exec_command_copyright(scan_state, active_branch);
312 	else if (strcmp(cmd, "crosstabview") == 0)
313 		status = exec_command_crosstabview(scan_state, active_branch);
314 	else if (cmd[0] == 'd')
315 		status = exec_command_d(scan_state, active_branch, cmd);
316 	else if (strcmp(cmd, "e") == 0 || strcmp(cmd, "edit") == 0)
317 		status = exec_command_edit(scan_state, active_branch,
318 								   query_buf, previous_buf);
319 	else if (strcmp(cmd, "ef") == 0)
320 		status = exec_command_ef_ev(scan_state, active_branch, query_buf, true);
321 	else if (strcmp(cmd, "ev") == 0)
322 		status = exec_command_ef_ev(scan_state, active_branch, query_buf, false);
323 	else if (strcmp(cmd, "echo") == 0 || strcmp(cmd, "qecho") == 0)
324 		status = exec_command_echo(scan_state, active_branch, cmd);
325 	else if (strcmp(cmd, "elif") == 0)
326 		status = exec_command_elif(scan_state, cstack, query_buf);
327 	else if (strcmp(cmd, "else") == 0)
328 		status = exec_command_else(scan_state, cstack, query_buf);
329 	else if (strcmp(cmd, "endif") == 0)
330 		status = exec_command_endif(scan_state, cstack, query_buf);
331 	else if (strcmp(cmd, "encoding") == 0)
332 		status = exec_command_encoding(scan_state, active_branch);
333 	else if (strcmp(cmd, "errverbose") == 0)
334 		status = exec_command_errverbose(scan_state, active_branch);
335 	else if (strcmp(cmd, "f") == 0)
336 		status = exec_command_f(scan_state, active_branch);
337 	else if (strcmp(cmd, "g") == 0 || strcmp(cmd, "gx") == 0)
338 		status = exec_command_g(scan_state, active_branch, cmd);
339 	else if (strcmp(cmd, "gdesc") == 0)
340 		status = exec_command_gdesc(scan_state, active_branch);
341 	else if (strcmp(cmd, "gexec") == 0)
342 		status = exec_command_gexec(scan_state, active_branch);
343 	else if (strcmp(cmd, "gset") == 0)
344 		status = exec_command_gset(scan_state, active_branch);
345 	else if (strcmp(cmd, "h") == 0 || strcmp(cmd, "help") == 0)
346 		status = exec_command_help(scan_state, active_branch);
347 	else if (strcmp(cmd, "H") == 0 || strcmp(cmd, "html") == 0)
348 		status = exec_command_html(scan_state, active_branch);
349 	else if (strcmp(cmd, "i") == 0 || strcmp(cmd, "include") == 0 ||
350 			 strcmp(cmd, "ir") == 0 || strcmp(cmd, "include_relative") == 0)
351 		status = exec_command_include(scan_state, active_branch, cmd);
352 	else if (strcmp(cmd, "if") == 0)
353 		status = exec_command_if(scan_state, cstack, query_buf);
354 	else if (strcmp(cmd, "l") == 0 || strcmp(cmd, "list") == 0 ||
355 			 strcmp(cmd, "l+") == 0 || strcmp(cmd, "list+") == 0)
356 		status = exec_command_list(scan_state, active_branch, cmd);
357 	else if (strncmp(cmd, "lo_", 3) == 0)
358 		status = exec_command_lo(scan_state, active_branch, cmd);
359 	else if (strcmp(cmd, "o") == 0 || strcmp(cmd, "out") == 0)
360 		status = exec_command_out(scan_state, active_branch);
361 	else if (strcmp(cmd, "p") == 0 || strcmp(cmd, "print") == 0)
362 		status = exec_command_print(scan_state, active_branch,
363 									query_buf, previous_buf);
364 	else if (strcmp(cmd, "password") == 0)
365 		status = exec_command_password(scan_state, active_branch);
366 	else if (strcmp(cmd, "prompt") == 0)
367 		status = exec_command_prompt(scan_state, active_branch, cmd);
368 	else if (strcmp(cmd, "pset") == 0)
369 		status = exec_command_pset(scan_state, active_branch);
370 	else if (strcmp(cmd, "q") == 0 || strcmp(cmd, "quit") == 0)
371 		status = exec_command_quit(scan_state, active_branch);
372 	else if (strcmp(cmd, "r") == 0 || strcmp(cmd, "reset") == 0)
373 		status = exec_command_reset(scan_state, active_branch, query_buf);
374 	else if (strcmp(cmd, "s") == 0)
375 		status = exec_command_s(scan_state, active_branch);
376 	else if (strcmp(cmd, "set") == 0)
377 		status = exec_command_set(scan_state, active_branch);
378 	else if (strcmp(cmd, "setenv") == 0)
379 		status = exec_command_setenv(scan_state, active_branch, cmd);
380 	else if (strcmp(cmd, "sf") == 0 || strcmp(cmd, "sf+") == 0)
381 		status = exec_command_sf_sv(scan_state, active_branch, cmd, true);
382 	else if (strcmp(cmd, "sv") == 0 || strcmp(cmd, "sv+") == 0)
383 		status = exec_command_sf_sv(scan_state, active_branch, cmd, false);
384 	else if (strcmp(cmd, "t") == 0)
385 		status = exec_command_t(scan_state, active_branch);
386 	else if (strcmp(cmd, "T") == 0)
387 		status = exec_command_T(scan_state, active_branch);
388 	else if (strcmp(cmd, "timing") == 0)
389 		status = exec_command_timing(scan_state, active_branch);
390 	else if (strcmp(cmd, "unset") == 0)
391 		status = exec_command_unset(scan_state, active_branch, cmd);
392 	else if (strcmp(cmd, "w") == 0 || strcmp(cmd, "write") == 0)
393 		status = exec_command_write(scan_state, active_branch, cmd,
394 									query_buf, previous_buf);
395 	else if (strcmp(cmd, "watch") == 0)
396 		status = exec_command_watch(scan_state, active_branch,
397 									query_buf, previous_buf);
398 	else if (strcmp(cmd, "x") == 0)
399 		status = exec_command_x(scan_state, active_branch);
400 	else if (strcmp(cmd, "z") == 0)
401 		status = exec_command_z(scan_state, active_branch);
402 	else if (strcmp(cmd, "!") == 0)
403 		status = exec_command_shell_escape(scan_state, active_branch);
404 	else if (strcmp(cmd, "?") == 0)
405 		status = exec_command_slash_command_help(scan_state, active_branch);
406 	else
407 		status = PSQL_CMD_UNKNOWN;
408 
409 	/*
410 	 * All the commands that return PSQL_CMD_SEND want to execute previous_buf
411 	 * if query_buf is empty.  For convenience we implement that here, not in
412 	 * the individual command subroutines.
413 	 */
414 	if (status == PSQL_CMD_SEND)
415 		copy_previous_query(query_buf, previous_buf);
416 
417 	return status;
418 }
419 
420 
421 /*
422  * \a -- toggle field alignment
423  *
424  * This makes little sense but we keep it around.
425  */
426 static backslashResult
exec_command_a(PsqlScanState scan_state,bool active_branch)427 exec_command_a(PsqlScanState scan_state, bool active_branch)
428 {
429 	bool		success = true;
430 
431 	if (active_branch)
432 	{
433 		if (pset.popt.topt.format != PRINT_ALIGNED)
434 			success = do_pset("format", "aligned", &pset.popt, pset.quiet);
435 		else
436 			success = do_pset("format", "unaligned", &pset.popt, pset.quiet);
437 	}
438 
439 	return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
440 }
441 
442 /*
443  * \C -- override table title (formerly change HTML caption)
444  */
445 static backslashResult
exec_command_C(PsqlScanState scan_state,bool active_branch)446 exec_command_C(PsqlScanState scan_state, bool active_branch)
447 {
448 	bool		success = true;
449 
450 	if (active_branch)
451 	{
452 		char	   *opt = psql_scan_slash_option(scan_state,
453 												 OT_NORMAL, NULL, true);
454 
455 		success = do_pset("title", opt, &pset.popt, pset.quiet);
456 		free(opt);
457 	}
458 	else
459 		ignore_slash_options(scan_state);
460 
461 	return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
462 }
463 
464 /*
465  * \c or \connect -- connect to database using the specified parameters.
466  *
467  * \c [-reuse-previous=BOOL] dbname user host port
468  *
469  * Specifying a parameter as '-' is equivalent to omitting it.  Examples:
470  *
471  * \c - - hst		Connect to current database on current port of
472  *					host "hst" as current user.
473  * \c - usr - prt	Connect to current database on port "prt" of current host
474  *					as user "usr".
475  * \c dbs			Connect to database "dbs" on current port of current host
476  *					as current user.
477  */
478 static backslashResult
exec_command_connect(PsqlScanState scan_state,bool active_branch)479 exec_command_connect(PsqlScanState scan_state, bool active_branch)
480 {
481 	bool		success = true;
482 
483 	if (active_branch)
484 	{
485 		static const char prefix[] = "-reuse-previous=";
486 		char	   *opt1,
487 				   *opt2,
488 				   *opt3,
489 				   *opt4;
490 		enum trivalue reuse_previous = TRI_DEFAULT;
491 
492 		opt1 = read_connect_arg(scan_state);
493 		if (opt1 != NULL && strncmp(opt1, prefix, sizeof(prefix) - 1) == 0)
494 		{
495 			bool		on_off;
496 
497 			success = ParseVariableBool(opt1 + sizeof(prefix) - 1,
498 										"-reuse-previous",
499 										&on_off);
500 			if (success)
501 			{
502 				reuse_previous = on_off ? TRI_YES : TRI_NO;
503 				free(opt1);
504 				opt1 = read_connect_arg(scan_state);
505 			}
506 		}
507 
508 		if (success)			/* give up if reuse_previous was invalid */
509 		{
510 			opt2 = read_connect_arg(scan_state);
511 			opt3 = read_connect_arg(scan_state);
512 			opt4 = read_connect_arg(scan_state);
513 
514 			success = do_connect(reuse_previous, opt1, opt2, opt3, opt4);
515 
516 			free(opt2);
517 			free(opt3);
518 			free(opt4);
519 		}
520 		free(opt1);
521 	}
522 	else
523 		ignore_slash_options(scan_state);
524 
525 	return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
526 }
527 
528 /*
529  * \cd -- change directory
530  */
531 static backslashResult
exec_command_cd(PsqlScanState scan_state,bool active_branch,const char * cmd)532 exec_command_cd(PsqlScanState scan_state, bool active_branch, const char *cmd)
533 {
534 	bool		success = true;
535 
536 	if (active_branch)
537 	{
538 		char	   *opt = psql_scan_slash_option(scan_state,
539 												 OT_NORMAL, NULL, true);
540 		char	   *dir;
541 
542 		if (opt)
543 			dir = opt;
544 		else
545 		{
546 #ifndef WIN32
547 			struct passwd *pw;
548 			uid_t		user_id = geteuid();
549 
550 			errno = 0;			/* clear errno before call */
551 			pw = getpwuid(user_id);
552 			if (!pw)
553 			{
554 				pg_log_error("could not get home directory for user ID %ld: %s",
555 							 (long) user_id,
556 							 errno ? strerror(errno) : _("user does not exist"));
557 				exit(EXIT_FAILURE);
558 			}
559 			dir = pw->pw_dir;
560 #else							/* WIN32 */
561 
562 			/*
563 			 * On Windows, 'cd' without arguments prints the current
564 			 * directory, so if someone wants to code this here instead...
565 			 */
566 			dir = "/";
567 #endif							/* WIN32 */
568 		}
569 
570 		if (chdir(dir) == -1)
571 		{
572 			pg_log_error("\\%s: could not change directory to \"%s\": %m",
573 						 cmd, dir);
574 			success = false;
575 		}
576 
577 		if (opt)
578 			free(opt);
579 	}
580 	else
581 		ignore_slash_options(scan_state);
582 
583 	return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
584 }
585 
586 /*
587  * \conninfo -- display information about the current connection
588  */
589 static backslashResult
exec_command_conninfo(PsqlScanState scan_state,bool active_branch)590 exec_command_conninfo(PsqlScanState scan_state, bool active_branch)
591 {
592 	if (active_branch)
593 	{
594 		char	   *db = PQdb(pset.db);
595 
596 		if (db == NULL)
597 			printf(_("You are currently not connected to a database.\n"));
598 		else
599 		{
600 			char	   *host = PQhost(pset.db);
601 			char	   *hostaddr = PQhostaddr(pset.db);
602 
603 			/*
604 			 * If the host is an absolute path, the connection is via socket
605 			 * unless overridden by hostaddr
606 			 */
607 			if (is_absolute_path(host))
608 			{
609 				if (hostaddr && *hostaddr)
610 					printf(_("You are connected to database \"%s\" as user \"%s\" on address \"%s\" at port \"%s\".\n"),
611 						   db, PQuser(pset.db), hostaddr, PQport(pset.db));
612 				else
613 					printf(_("You are connected to database \"%s\" as user \"%s\" via socket in \"%s\" at port \"%s\".\n"),
614 						   db, PQuser(pset.db), host, PQport(pset.db));
615 			}
616 			else
617 			{
618 				if (hostaddr && *hostaddr && strcmp(host, hostaddr) != 0)
619 					printf(_("You are connected to database \"%s\" as user \"%s\" on host \"%s\" (address \"%s\") at port \"%s\".\n"),
620 						   db, PQuser(pset.db), host, hostaddr, PQport(pset.db));
621 				else
622 					printf(_("You are connected to database \"%s\" as user \"%s\" on host \"%s\" at port \"%s\".\n"),
623 						   db, PQuser(pset.db), host, PQport(pset.db));
624 			}
625 			printSSLInfo();
626 			printGSSInfo();
627 		}
628 	}
629 
630 	return PSQL_CMD_SKIP_LINE;
631 }
632 
633 /*
634  * \copy -- run a COPY command
635  */
636 static backslashResult
exec_command_copy(PsqlScanState scan_state,bool active_branch)637 exec_command_copy(PsqlScanState scan_state, bool active_branch)
638 {
639 	bool		success = true;
640 
641 	if (active_branch)
642 	{
643 		char	   *opt = psql_scan_slash_option(scan_state,
644 												 OT_WHOLE_LINE, NULL, false);
645 
646 		success = do_copy(opt);
647 		free(opt);
648 	}
649 	else
650 		ignore_slash_whole_line(scan_state);
651 
652 	return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
653 }
654 
655 /*
656  * \copyright -- print copyright notice
657  */
658 static backslashResult
exec_command_copyright(PsqlScanState scan_state,bool active_branch)659 exec_command_copyright(PsqlScanState scan_state, bool active_branch)
660 {
661 	if (active_branch)
662 		print_copyright();
663 
664 	return PSQL_CMD_SKIP_LINE;
665 }
666 
667 /*
668  * \crosstabview -- execute a query and display results in crosstab
669  */
670 static backslashResult
exec_command_crosstabview(PsqlScanState scan_state,bool active_branch)671 exec_command_crosstabview(PsqlScanState scan_state, bool active_branch)
672 {
673 	backslashResult status = PSQL_CMD_SKIP_LINE;
674 
675 	if (active_branch)
676 	{
677 		int			i;
678 
679 		for (i = 0; i < lengthof(pset.ctv_args); i++)
680 			pset.ctv_args[i] = psql_scan_slash_option(scan_state,
681 													  OT_NORMAL, NULL, true);
682 		pset.crosstab_flag = true;
683 		status = PSQL_CMD_SEND;
684 	}
685 	else
686 		ignore_slash_options(scan_state);
687 
688 	return status;
689 }
690 
691 /*
692  * \d* commands
693  */
694 static backslashResult
exec_command_d(PsqlScanState scan_state,bool active_branch,const char * cmd)695 exec_command_d(PsqlScanState scan_state, bool active_branch, const char *cmd)
696 {
697 	backslashResult status = PSQL_CMD_SKIP_LINE;
698 	bool		success = true;
699 
700 	if (active_branch)
701 	{
702 		char	   *pattern;
703 		bool		show_verbose,
704 					show_system;
705 
706 		/* We don't do SQLID reduction on the pattern yet */
707 		pattern = psql_scan_slash_option(scan_state,
708 										 OT_NORMAL, NULL, true);
709 
710 		show_verbose = strchr(cmd, '+') ? true : false;
711 		show_system = strchr(cmd, 'S') ? true : false;
712 
713 		switch (cmd[1])
714 		{
715 			case '\0':
716 			case '+':
717 			case 'S':
718 				if (pattern)
719 					success = describeTableDetails(pattern, show_verbose, show_system);
720 				else
721 					/* standard listing of interesting things */
722 					success = listTables("tvmsE", NULL, show_verbose, show_system);
723 				break;
724 			case 'A':
725 				success = describeAccessMethods(pattern, show_verbose);
726 				break;
727 			case 'a':
728 				success = describeAggregates(pattern, show_verbose, show_system);
729 				break;
730 			case 'b':
731 				success = describeTablespaces(pattern, show_verbose);
732 				break;
733 			case 'c':
734 				success = listConversions(pattern, show_verbose, show_system);
735 				break;
736 			case 'C':
737 				success = listCasts(pattern, show_verbose);
738 				break;
739 			case 'd':
740 				if (strncmp(cmd, "ddp", 3) == 0)
741 					success = listDefaultACLs(pattern);
742 				else
743 					success = objectDescription(pattern, show_system);
744 				break;
745 			case 'D':
746 				success = listDomains(pattern, show_verbose, show_system);
747 				break;
748 			case 'f':			/* function subsystem */
749 				switch (cmd[2])
750 				{
751 					case '\0':
752 					case '+':
753 					case 'S':
754 					case 'a':
755 					case 'n':
756 					case 'p':
757 					case 't':
758 					case 'w':
759 						success = describeFunctions(&cmd[2], pattern, show_verbose, show_system);
760 						break;
761 					default:
762 						status = PSQL_CMD_UNKNOWN;
763 						break;
764 				}
765 				break;
766 			case 'g':
767 				/* no longer distinct from \du */
768 				success = describeRoles(pattern, show_verbose, show_system);
769 				break;
770 			case 'l':
771 				success = do_lo_list();
772 				break;
773 			case 'L':
774 				success = listLanguages(pattern, show_verbose, show_system);
775 				break;
776 			case 'n':
777 				success = listSchemas(pattern, show_verbose, show_system);
778 				break;
779 			case 'o':
780 				success = describeOperators(pattern, show_verbose, show_system);
781 				break;
782 			case 'O':
783 				success = listCollations(pattern, show_verbose, show_system);
784 				break;
785 			case 'p':
786 				success = permissionsList(pattern);
787 				break;
788 			case 'P':
789 				{
790 					switch (cmd[2])
791 					{
792 						case '\0':
793 						case '+':
794 						case 't':
795 						case 'i':
796 						case 'n':
797 							success = listPartitionedTables(&cmd[2], pattern, show_verbose);
798 							break;
799 						default:
800 							status = PSQL_CMD_UNKNOWN;
801 							break;
802 					}
803 				}
804 				break;
805 			case 'T':
806 				success = describeTypes(pattern, show_verbose, show_system);
807 				break;
808 			case 't':
809 			case 'v':
810 			case 'm':
811 			case 'i':
812 			case 's':
813 			case 'E':
814 				success = listTables(&cmd[1], pattern, show_verbose, show_system);
815 				break;
816 			case 'r':
817 				if (cmd[2] == 'd' && cmd[3] == 's')
818 				{
819 					char	   *pattern2 = NULL;
820 
821 					if (pattern)
822 						pattern2 = psql_scan_slash_option(scan_state,
823 														  OT_NORMAL, NULL, true);
824 					success = listDbRoleSettings(pattern, pattern2);
825 
826 					if (pattern2)
827 						free(pattern2);
828 				}
829 				else
830 					status = PSQL_CMD_UNKNOWN;
831 				break;
832 			case 'R':
833 				switch (cmd[2])
834 				{
835 					case 'p':
836 						if (show_verbose)
837 							success = describePublications(pattern);
838 						else
839 							success = listPublications(pattern);
840 						break;
841 					case 's':
842 						success = describeSubscriptions(pattern, show_verbose);
843 						break;
844 					default:
845 						status = PSQL_CMD_UNKNOWN;
846 				}
847 				break;
848 			case 'u':
849 				success = describeRoles(pattern, show_verbose, show_system);
850 				break;
851 			case 'F':			/* text search subsystem */
852 				switch (cmd[2])
853 				{
854 					case '\0':
855 					case '+':
856 						success = listTSConfigs(pattern, show_verbose);
857 						break;
858 					case 'p':
859 						success = listTSParsers(pattern, show_verbose);
860 						break;
861 					case 'd':
862 						success = listTSDictionaries(pattern, show_verbose);
863 						break;
864 					case 't':
865 						success = listTSTemplates(pattern, show_verbose);
866 						break;
867 					default:
868 						status = PSQL_CMD_UNKNOWN;
869 						break;
870 				}
871 				break;
872 			case 'e':			/* SQL/MED subsystem */
873 				switch (cmd[2])
874 				{
875 					case 's':
876 						success = listForeignServers(pattern, show_verbose);
877 						break;
878 					case 'u':
879 						success = listUserMappings(pattern, show_verbose);
880 						break;
881 					case 'w':
882 						success = listForeignDataWrappers(pattern, show_verbose);
883 						break;
884 					case 't':
885 						success = listForeignTables(pattern, show_verbose);
886 						break;
887 					default:
888 						status = PSQL_CMD_UNKNOWN;
889 						break;
890 				}
891 				break;
892 			case 'x':			/* Extensions */
893 				if (show_verbose)
894 					success = listExtensionContents(pattern);
895 				else
896 					success = listExtensions(pattern);
897 				break;
898 			case 'y':			/* Event Triggers */
899 				success = listEventTriggers(pattern, show_verbose);
900 				break;
901 			default:
902 				status = PSQL_CMD_UNKNOWN;
903 		}
904 
905 		if (pattern)
906 			free(pattern);
907 	}
908 	else
909 		ignore_slash_options(scan_state);
910 
911 	if (!success)
912 		status = PSQL_CMD_ERROR;
913 
914 	return status;
915 }
916 
917 /*
918  * \e or \edit -- edit the current query buffer, or edit a file and
919  * make it the query buffer
920  */
921 static backslashResult
exec_command_edit(PsqlScanState scan_state,bool active_branch,PQExpBuffer query_buf,PQExpBuffer previous_buf)922 exec_command_edit(PsqlScanState scan_state, bool active_branch,
923 				  PQExpBuffer query_buf, PQExpBuffer previous_buf)
924 {
925 	backslashResult status = PSQL_CMD_SKIP_LINE;
926 
927 	if (active_branch)
928 	{
929 		if (!query_buf)
930 		{
931 			pg_log_error("no query buffer");
932 			status = PSQL_CMD_ERROR;
933 		}
934 		else
935 		{
936 			char	   *fname;
937 			char	   *ln = NULL;
938 			int			lineno = -1;
939 
940 			fname = psql_scan_slash_option(scan_state,
941 										   OT_NORMAL, NULL, true);
942 			if (fname)
943 			{
944 				/* try to get separate lineno arg */
945 				ln = psql_scan_slash_option(scan_state,
946 											OT_NORMAL, NULL, true);
947 				if (ln == NULL)
948 				{
949 					/* only one arg; maybe it is lineno not fname */
950 					if (fname[0] &&
951 						strspn(fname, "0123456789") == strlen(fname))
952 					{
953 						/* all digits, so assume it is lineno */
954 						ln = fname;
955 						fname = NULL;
956 					}
957 				}
958 			}
959 			if (ln)
960 			{
961 				lineno = atoi(ln);
962 				if (lineno < 1)
963 				{
964 					pg_log_error("invalid line number: %s", ln);
965 					status = PSQL_CMD_ERROR;
966 				}
967 			}
968 			if (status != PSQL_CMD_ERROR)
969 			{
970 				expand_tilde(&fname);
971 				if (fname)
972 					canonicalize_path(fname);
973 
974 				/* If query_buf is empty, recall previous query for editing */
975 				copy_previous_query(query_buf, previous_buf);
976 
977 				if (do_edit(fname, query_buf, lineno, NULL))
978 					status = PSQL_CMD_NEWEDIT;
979 				else
980 					status = PSQL_CMD_ERROR;
981 			}
982 			if (fname)
983 				free(fname);
984 			if (ln)
985 				free(ln);
986 		}
987 	}
988 	else
989 		ignore_slash_options(scan_state);
990 
991 	return status;
992 }
993 
994 /*
995  * \ef/\ev -- edit the named function/view, or
996  * present a blank CREATE FUNCTION/VIEW template if no argument is given
997  */
998 static backslashResult
exec_command_ef_ev(PsqlScanState scan_state,bool active_branch,PQExpBuffer query_buf,bool is_func)999 exec_command_ef_ev(PsqlScanState scan_state, bool active_branch,
1000 				   PQExpBuffer query_buf, bool is_func)
1001 {
1002 	backslashResult status = PSQL_CMD_SKIP_LINE;
1003 
1004 	if (active_branch)
1005 	{
1006 		char	   *obj_desc = psql_scan_slash_option(scan_state,
1007 													  OT_WHOLE_LINE,
1008 													  NULL, true);
1009 		int			lineno = -1;
1010 
1011 		if (pset.sversion < (is_func ? 80400 : 70400))
1012 		{
1013 			char		sverbuf[32];
1014 
1015 			formatPGVersionNumber(pset.sversion, false,
1016 								  sverbuf, sizeof(sverbuf));
1017 			if (is_func)
1018 				pg_log_error("The server (version %s) does not support editing function source.",
1019 							 sverbuf);
1020 			else
1021 				pg_log_error("The server (version %s) does not support editing view definitions.",
1022 							 sverbuf);
1023 			status = PSQL_CMD_ERROR;
1024 		}
1025 		else if (!query_buf)
1026 		{
1027 			pg_log_error("no query buffer");
1028 			status = PSQL_CMD_ERROR;
1029 		}
1030 		else
1031 		{
1032 			Oid			obj_oid = InvalidOid;
1033 			EditableObjectType eot = is_func ? EditableFunction : EditableView;
1034 
1035 			lineno = strip_lineno_from_objdesc(obj_desc);
1036 			if (lineno == 0)
1037 			{
1038 				/* error already reported */
1039 				status = PSQL_CMD_ERROR;
1040 			}
1041 			else if (!obj_desc)
1042 			{
1043 				/* set up an empty command to fill in */
1044 				resetPQExpBuffer(query_buf);
1045 				if (is_func)
1046 					appendPQExpBufferStr(query_buf,
1047 										 "CREATE FUNCTION ( )\n"
1048 										 " RETURNS \n"
1049 										 " LANGUAGE \n"
1050 										 " -- common options:  IMMUTABLE  STABLE  STRICT  SECURITY DEFINER\n"
1051 										 "AS $function$\n"
1052 										 "\n$function$\n");
1053 				else
1054 					appendPQExpBufferStr(query_buf,
1055 										 "CREATE VIEW  AS\n"
1056 										 " SELECT \n"
1057 										 "  -- something...\n");
1058 			}
1059 			else if (!lookup_object_oid(eot, obj_desc, &obj_oid))
1060 			{
1061 				/* error already reported */
1062 				status = PSQL_CMD_ERROR;
1063 			}
1064 			else if (!get_create_object_cmd(eot, obj_oid, query_buf))
1065 			{
1066 				/* error already reported */
1067 				status = PSQL_CMD_ERROR;
1068 			}
1069 			else if (is_func && lineno > 0)
1070 			{
1071 				/*
1072 				 * lineno "1" should correspond to the first line of the
1073 				 * function body.  We expect that pg_get_functiondef() will
1074 				 * emit that on a line beginning with "AS ", and that there
1075 				 * can be no such line before the real start of the function
1076 				 * body.  Increment lineno by the number of lines before that
1077 				 * line, so that it becomes relative to the first line of the
1078 				 * function definition.
1079 				 */
1080 				const char *lines = query_buf->data;
1081 
1082 				while (*lines != '\0')
1083 				{
1084 					if (strncmp(lines, "AS ", 3) == 0)
1085 						break;
1086 					lineno++;
1087 					/* find start of next line */
1088 					lines = strchr(lines, '\n');
1089 					if (!lines)
1090 						break;
1091 					lines++;
1092 				}
1093 			}
1094 		}
1095 
1096 		if (status != PSQL_CMD_ERROR)
1097 		{
1098 			bool		edited = false;
1099 
1100 			if (!do_edit(NULL, query_buf, lineno, &edited))
1101 				status = PSQL_CMD_ERROR;
1102 			else if (!edited)
1103 				puts(_("No changes"));
1104 			else
1105 				status = PSQL_CMD_NEWEDIT;
1106 		}
1107 
1108 		if (obj_desc)
1109 			free(obj_desc);
1110 	}
1111 	else
1112 		ignore_slash_whole_line(scan_state);
1113 
1114 	return status;
1115 }
1116 
1117 /*
1118  * \echo and \qecho -- echo arguments to stdout or query output
1119  */
1120 static backslashResult
exec_command_echo(PsqlScanState scan_state,bool active_branch,const char * cmd)1121 exec_command_echo(PsqlScanState scan_state, bool active_branch, const char *cmd)
1122 {
1123 	if (active_branch)
1124 	{
1125 		char	   *value;
1126 		char		quoted;
1127 		bool		no_newline = false;
1128 		bool		first = true;
1129 		FILE	   *fout;
1130 
1131 		if (strcmp(cmd, "qecho") == 0)
1132 			fout = pset.queryFout;
1133 		else
1134 			fout = stdout;
1135 
1136 		while ((value = psql_scan_slash_option(scan_state,
1137 											   OT_NORMAL, &quoted, false)))
1138 		{
1139 			if (!quoted && strcmp(value, "-n") == 0)
1140 				no_newline = true;
1141 			else
1142 			{
1143 				if (first)
1144 					first = false;
1145 				else
1146 					fputc(' ', fout);
1147 				fputs(value, fout);
1148 			}
1149 			free(value);
1150 		}
1151 		if (!no_newline)
1152 			fputs("\n", fout);
1153 	}
1154 	else
1155 		ignore_slash_options(scan_state);
1156 
1157 	return PSQL_CMD_SKIP_LINE;
1158 }
1159 
1160 /*
1161  * \encoding -- set/show client side encoding
1162  */
1163 static backslashResult
exec_command_encoding(PsqlScanState scan_state,bool active_branch)1164 exec_command_encoding(PsqlScanState scan_state, bool active_branch)
1165 {
1166 	if (active_branch)
1167 	{
1168 		char	   *encoding = psql_scan_slash_option(scan_state,
1169 													  OT_NORMAL, NULL, false);
1170 
1171 		if (!encoding)
1172 		{
1173 			/* show encoding */
1174 			puts(pg_encoding_to_char(pset.encoding));
1175 		}
1176 		else
1177 		{
1178 			/* set encoding */
1179 			if (PQsetClientEncoding(pset.db, encoding) == -1)
1180 				pg_log_error("%s: invalid encoding name or conversion procedure not found", encoding);
1181 			else
1182 			{
1183 				/* save encoding info into psql internal data */
1184 				pset.encoding = PQclientEncoding(pset.db);
1185 				pset.popt.topt.encoding = pset.encoding;
1186 				SetVariable(pset.vars, "ENCODING",
1187 							pg_encoding_to_char(pset.encoding));
1188 			}
1189 			free(encoding);
1190 		}
1191 	}
1192 	else
1193 		ignore_slash_options(scan_state);
1194 
1195 	return PSQL_CMD_SKIP_LINE;
1196 }
1197 
1198 /*
1199  * \errverbose -- display verbose message from last failed query
1200  */
1201 static backslashResult
exec_command_errverbose(PsqlScanState scan_state,bool active_branch)1202 exec_command_errverbose(PsqlScanState scan_state, bool active_branch)
1203 {
1204 	if (active_branch)
1205 	{
1206 		if (pset.last_error_result)
1207 		{
1208 			char	   *msg;
1209 
1210 			msg = PQresultVerboseErrorMessage(pset.last_error_result,
1211 											  PQERRORS_VERBOSE,
1212 											  PQSHOW_CONTEXT_ALWAYS);
1213 			if (msg)
1214 			{
1215 				pg_log_error("%s", msg);
1216 				PQfreemem(msg);
1217 			}
1218 			else
1219 				puts(_("out of memory"));
1220 		}
1221 		else
1222 			puts(_("There is no previous error."));
1223 	}
1224 
1225 	return PSQL_CMD_SKIP_LINE;
1226 }
1227 
1228 /*
1229  * \f -- change field separator
1230  */
1231 static backslashResult
exec_command_f(PsqlScanState scan_state,bool active_branch)1232 exec_command_f(PsqlScanState scan_state, bool active_branch)
1233 {
1234 	bool		success = true;
1235 
1236 	if (active_branch)
1237 	{
1238 		char	   *fname = psql_scan_slash_option(scan_state,
1239 												   OT_NORMAL, NULL, false);
1240 
1241 		success = do_pset("fieldsep", fname, &pset.popt, pset.quiet);
1242 		free(fname);
1243 	}
1244 	else
1245 		ignore_slash_options(scan_state);
1246 
1247 	return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
1248 }
1249 
1250 /*
1251  * \g [filename] -- send query, optionally with output to file/pipe
1252  * \gx [filename] -- same as \g, with expanded mode forced
1253  */
1254 static backslashResult
exec_command_g(PsqlScanState scan_state,bool active_branch,const char * cmd)1255 exec_command_g(PsqlScanState scan_state, bool active_branch, const char *cmd)
1256 {
1257 	backslashResult status = PSQL_CMD_SKIP_LINE;
1258 
1259 	if (active_branch)
1260 	{
1261 		char	   *fname = psql_scan_slash_option(scan_state,
1262 												   OT_FILEPIPE, NULL, false);
1263 
1264 		if (!fname)
1265 			pset.gfname = NULL;
1266 		else
1267 		{
1268 			expand_tilde(&fname);
1269 			pset.gfname = pg_strdup(fname);
1270 		}
1271 		free(fname);
1272 		if (strcmp(cmd, "gx") == 0)
1273 			pset.g_expanded = true;
1274 		status = PSQL_CMD_SEND;
1275 	}
1276 	else
1277 		ignore_slash_filepipe(scan_state);
1278 
1279 	return status;
1280 }
1281 
1282 /*
1283  * \gdesc -- describe query result
1284  */
1285 static backslashResult
exec_command_gdesc(PsqlScanState scan_state,bool active_branch)1286 exec_command_gdesc(PsqlScanState scan_state, bool active_branch)
1287 {
1288 	backslashResult status = PSQL_CMD_SKIP_LINE;
1289 
1290 	if (active_branch)
1291 	{
1292 		pset.gdesc_flag = true;
1293 		status = PSQL_CMD_SEND;
1294 	}
1295 
1296 	return status;
1297 }
1298 
1299 /*
1300  * \gexec -- send query and execute each field of result
1301  */
1302 static backslashResult
exec_command_gexec(PsqlScanState scan_state,bool active_branch)1303 exec_command_gexec(PsqlScanState scan_state, bool active_branch)
1304 {
1305 	backslashResult status = PSQL_CMD_SKIP_LINE;
1306 
1307 	if (active_branch)
1308 	{
1309 		pset.gexec_flag = true;
1310 		status = PSQL_CMD_SEND;
1311 	}
1312 
1313 	return status;
1314 }
1315 
1316 /*
1317  * \gset [prefix] -- send query and store result into variables
1318  */
1319 static backslashResult
exec_command_gset(PsqlScanState scan_state,bool active_branch)1320 exec_command_gset(PsqlScanState scan_state, bool active_branch)
1321 {
1322 	backslashResult status = PSQL_CMD_SKIP_LINE;
1323 
1324 	if (active_branch)
1325 	{
1326 		char	   *prefix = psql_scan_slash_option(scan_state,
1327 													OT_NORMAL, NULL, false);
1328 
1329 		if (prefix)
1330 			pset.gset_prefix = prefix;
1331 		else
1332 		{
1333 			/* we must set a non-NULL prefix to trigger storing */
1334 			pset.gset_prefix = pg_strdup("");
1335 		}
1336 		/* gset_prefix is freed later */
1337 		status = PSQL_CMD_SEND;
1338 	}
1339 	else
1340 		ignore_slash_options(scan_state);
1341 
1342 	return status;
1343 }
1344 
1345 /*
1346  * \help [topic] -- print help about SQL commands
1347  */
1348 static backslashResult
exec_command_help(PsqlScanState scan_state,bool active_branch)1349 exec_command_help(PsqlScanState scan_state, bool active_branch)
1350 {
1351 	if (active_branch)
1352 	{
1353 		char	   *opt = psql_scan_slash_option(scan_state,
1354 												 OT_WHOLE_LINE, NULL, false);
1355 		size_t		len;
1356 
1357 		/* strip any trailing spaces and semicolons */
1358 		if (opt)
1359 		{
1360 			len = strlen(opt);
1361 			while (len > 0 &&
1362 				   (isspace((unsigned char) opt[len - 1])
1363 					|| opt[len - 1] == ';'))
1364 				opt[--len] = '\0';
1365 		}
1366 
1367 		helpSQL(opt, pset.popt.topt.pager);
1368 		free(opt);
1369 	}
1370 	else
1371 		ignore_slash_whole_line(scan_state);
1372 
1373 	return PSQL_CMD_SKIP_LINE;
1374 }
1375 
1376 /*
1377  * \H and \html -- toggle HTML formatting
1378  */
1379 static backslashResult
exec_command_html(PsqlScanState scan_state,bool active_branch)1380 exec_command_html(PsqlScanState scan_state, bool active_branch)
1381 {
1382 	bool		success = true;
1383 
1384 	if (active_branch)
1385 	{
1386 		if (pset.popt.topt.format != PRINT_HTML)
1387 			success = do_pset("format", "html", &pset.popt, pset.quiet);
1388 		else
1389 			success = do_pset("format", "aligned", &pset.popt, pset.quiet);
1390 	}
1391 
1392 	return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
1393 }
1394 
1395 /*
1396  * \i and \ir -- include a file
1397  */
1398 static backslashResult
exec_command_include(PsqlScanState scan_state,bool active_branch,const char * cmd)1399 exec_command_include(PsqlScanState scan_state, bool active_branch, const char *cmd)
1400 {
1401 	bool		success = true;
1402 
1403 	if (active_branch)
1404 	{
1405 		char	   *fname = psql_scan_slash_option(scan_state,
1406 												   OT_NORMAL, NULL, true);
1407 
1408 		if (!fname)
1409 		{
1410 			pg_log_error("\\%s: missing required argument", cmd);
1411 			success = false;
1412 		}
1413 		else
1414 		{
1415 			bool		include_relative;
1416 
1417 			include_relative = (strcmp(cmd, "ir") == 0
1418 								|| strcmp(cmd, "include_relative") == 0);
1419 			expand_tilde(&fname);
1420 			success = (process_file(fname, include_relative) == EXIT_SUCCESS);
1421 			free(fname);
1422 		}
1423 	}
1424 	else
1425 		ignore_slash_options(scan_state);
1426 
1427 	return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
1428 }
1429 
1430 /*
1431  * \if <expr> -- beginning of an \if..\endif block
1432  *
1433  * <expr> is parsed as a boolean expression.  Invalid expressions will emit a
1434  * warning and be treated as false.  Statements that follow a false expression
1435  * will be parsed but ignored.  Note that in the case where an \if statement
1436  * is itself within an inactive section of a block, then the entire inner
1437  * \if..\endif block will be parsed but ignored.
1438  */
1439 static backslashResult
exec_command_if(PsqlScanState scan_state,ConditionalStack cstack,PQExpBuffer query_buf)1440 exec_command_if(PsqlScanState scan_state, ConditionalStack cstack,
1441 				PQExpBuffer query_buf)
1442 {
1443 	if (conditional_active(cstack))
1444 	{
1445 		/*
1446 		 * First, push a new active stack entry; this ensures that the lexer
1447 		 * will perform variable substitution and backtick evaluation while
1448 		 * scanning the expression.  (That should happen anyway, since we know
1449 		 * we're in an active outer branch, but let's be sure.)
1450 		 */
1451 		conditional_stack_push(cstack, IFSTATE_TRUE);
1452 
1453 		/* Remember current query state in case we need to restore later */
1454 		save_query_text_state(scan_state, cstack, query_buf);
1455 
1456 		/*
1457 		 * Evaluate the expression; if it's false, change to inactive state.
1458 		 */
1459 		if (!is_true_boolean_expression(scan_state, "\\if expression"))
1460 			conditional_stack_poke(cstack, IFSTATE_FALSE);
1461 	}
1462 	else
1463 	{
1464 		/*
1465 		 * We're within an inactive outer branch, so this entire \if block
1466 		 * will be ignored.  We don't want to evaluate the expression, so push
1467 		 * the "ignored" stack state before scanning it.
1468 		 */
1469 		conditional_stack_push(cstack, IFSTATE_IGNORED);
1470 
1471 		/* Remember current query state in case we need to restore later */
1472 		save_query_text_state(scan_state, cstack, query_buf);
1473 
1474 		ignore_boolean_expression(scan_state);
1475 	}
1476 
1477 	return PSQL_CMD_SKIP_LINE;
1478 }
1479 
1480 /*
1481  * \elif <expr> -- alternative branch in an \if..\endif block
1482  *
1483  * <expr> is evaluated the same as in \if <expr>.
1484  */
1485 static backslashResult
exec_command_elif(PsqlScanState scan_state,ConditionalStack cstack,PQExpBuffer query_buf)1486 exec_command_elif(PsqlScanState scan_state, ConditionalStack cstack,
1487 				  PQExpBuffer query_buf)
1488 {
1489 	bool		success = true;
1490 
1491 	switch (conditional_stack_peek(cstack))
1492 	{
1493 		case IFSTATE_TRUE:
1494 
1495 			/*
1496 			 * Just finished active branch of this \if block.  Update saved
1497 			 * state so we will keep whatever data was put in query_buf by the
1498 			 * active branch.
1499 			 */
1500 			save_query_text_state(scan_state, cstack, query_buf);
1501 
1502 			/*
1503 			 * Discard \elif expression and ignore the rest until \endif.
1504 			 * Switch state before reading expression to ensure proper lexer
1505 			 * behavior.
1506 			 */
1507 			conditional_stack_poke(cstack, IFSTATE_IGNORED);
1508 			ignore_boolean_expression(scan_state);
1509 			break;
1510 		case IFSTATE_FALSE:
1511 
1512 			/*
1513 			 * Discard any query text added by the just-skipped branch.
1514 			 */
1515 			discard_query_text(scan_state, cstack, query_buf);
1516 
1517 			/*
1518 			 * Have not yet found a true expression in this \if block, so this
1519 			 * might be the first.  We have to change state before examining
1520 			 * the expression, or the lexer won't do the right thing.
1521 			 */
1522 			conditional_stack_poke(cstack, IFSTATE_TRUE);
1523 			if (!is_true_boolean_expression(scan_state, "\\elif expression"))
1524 				conditional_stack_poke(cstack, IFSTATE_FALSE);
1525 			break;
1526 		case IFSTATE_IGNORED:
1527 
1528 			/*
1529 			 * Discard any query text added by the just-skipped branch.
1530 			 */
1531 			discard_query_text(scan_state, cstack, query_buf);
1532 
1533 			/*
1534 			 * Skip expression and move on.  Either the \if block already had
1535 			 * an active section, or whole block is being skipped.
1536 			 */
1537 			ignore_boolean_expression(scan_state);
1538 			break;
1539 		case IFSTATE_ELSE_TRUE:
1540 		case IFSTATE_ELSE_FALSE:
1541 			pg_log_error("\\elif: cannot occur after \\else");
1542 			success = false;
1543 			break;
1544 		case IFSTATE_NONE:
1545 			/* no \if to elif from */
1546 			pg_log_error("\\elif: no matching \\if");
1547 			success = false;
1548 			break;
1549 	}
1550 
1551 	return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
1552 }
1553 
1554 /*
1555  * \else -- final alternative in an \if..\endif block
1556  *
1557  * Statements within an \else branch will only be executed if
1558  * all previous \if and \elif expressions evaluated to false
1559  * and the block was not itself being ignored.
1560  */
1561 static backslashResult
exec_command_else(PsqlScanState scan_state,ConditionalStack cstack,PQExpBuffer query_buf)1562 exec_command_else(PsqlScanState scan_state, ConditionalStack cstack,
1563 				  PQExpBuffer query_buf)
1564 {
1565 	bool		success = true;
1566 
1567 	switch (conditional_stack_peek(cstack))
1568 	{
1569 		case IFSTATE_TRUE:
1570 
1571 			/*
1572 			 * Just finished active branch of this \if block.  Update saved
1573 			 * state so we will keep whatever data was put in query_buf by the
1574 			 * active branch.
1575 			 */
1576 			save_query_text_state(scan_state, cstack, query_buf);
1577 
1578 			/* Now skip the \else branch */
1579 			conditional_stack_poke(cstack, IFSTATE_ELSE_FALSE);
1580 			break;
1581 		case IFSTATE_FALSE:
1582 
1583 			/*
1584 			 * Discard any query text added by the just-skipped branch.
1585 			 */
1586 			discard_query_text(scan_state, cstack, query_buf);
1587 
1588 			/*
1589 			 * We've not found any true \if or \elif expression, so execute
1590 			 * the \else branch.
1591 			 */
1592 			conditional_stack_poke(cstack, IFSTATE_ELSE_TRUE);
1593 			break;
1594 		case IFSTATE_IGNORED:
1595 
1596 			/*
1597 			 * Discard any query text added by the just-skipped branch.
1598 			 */
1599 			discard_query_text(scan_state, cstack, query_buf);
1600 
1601 			/*
1602 			 * Either we previously processed the active branch of this \if,
1603 			 * or the whole \if block is being skipped.  Either way, skip the
1604 			 * \else branch.
1605 			 */
1606 			conditional_stack_poke(cstack, IFSTATE_ELSE_FALSE);
1607 			break;
1608 		case IFSTATE_ELSE_TRUE:
1609 		case IFSTATE_ELSE_FALSE:
1610 			pg_log_error("\\else: cannot occur after \\else");
1611 			success = false;
1612 			break;
1613 		case IFSTATE_NONE:
1614 			/* no \if to else from */
1615 			pg_log_error("\\else: no matching \\if");
1616 			success = false;
1617 			break;
1618 	}
1619 
1620 	return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
1621 }
1622 
1623 /*
1624  * \endif -- ends an \if...\endif block
1625  */
1626 static backslashResult
exec_command_endif(PsqlScanState scan_state,ConditionalStack cstack,PQExpBuffer query_buf)1627 exec_command_endif(PsqlScanState scan_state, ConditionalStack cstack,
1628 				   PQExpBuffer query_buf)
1629 {
1630 	bool		success = true;
1631 
1632 	switch (conditional_stack_peek(cstack))
1633 	{
1634 		case IFSTATE_TRUE:
1635 		case IFSTATE_ELSE_TRUE:
1636 			/* Close the \if block, keeping the query text */
1637 			success = conditional_stack_pop(cstack);
1638 			Assert(success);
1639 			break;
1640 		case IFSTATE_FALSE:
1641 		case IFSTATE_IGNORED:
1642 		case IFSTATE_ELSE_FALSE:
1643 
1644 			/*
1645 			 * Discard any query text added by the just-skipped branch.
1646 			 */
1647 			discard_query_text(scan_state, cstack, query_buf);
1648 
1649 			/* Close the \if block */
1650 			success = conditional_stack_pop(cstack);
1651 			Assert(success);
1652 			break;
1653 		case IFSTATE_NONE:
1654 			/* no \if to end */
1655 			pg_log_error("\\endif: no matching \\if");
1656 			success = false;
1657 			break;
1658 	}
1659 
1660 	return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
1661 }
1662 
1663 /*
1664  * \l -- list databases
1665  */
1666 static backslashResult
exec_command_list(PsqlScanState scan_state,bool active_branch,const char * cmd)1667 exec_command_list(PsqlScanState scan_state, bool active_branch, const char *cmd)
1668 {
1669 	bool		success = true;
1670 
1671 	if (active_branch)
1672 	{
1673 		char	   *pattern;
1674 		bool		show_verbose;
1675 
1676 		pattern = psql_scan_slash_option(scan_state,
1677 										 OT_NORMAL, NULL, true);
1678 
1679 		show_verbose = strchr(cmd, '+') ? true : false;
1680 
1681 		success = listAllDbs(pattern, show_verbose);
1682 
1683 		if (pattern)
1684 			free(pattern);
1685 	}
1686 	else
1687 		ignore_slash_options(scan_state);
1688 
1689 	return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
1690 }
1691 
1692 /*
1693  * \lo_* -- large object operations
1694  */
1695 static backslashResult
exec_command_lo(PsqlScanState scan_state,bool active_branch,const char * cmd)1696 exec_command_lo(PsqlScanState scan_state, bool active_branch, const char *cmd)
1697 {
1698 	backslashResult status = PSQL_CMD_SKIP_LINE;
1699 	bool		success = true;
1700 
1701 	if (active_branch)
1702 	{
1703 		char	   *opt1,
1704 				   *opt2;
1705 
1706 		opt1 = psql_scan_slash_option(scan_state,
1707 									  OT_NORMAL, NULL, true);
1708 		opt2 = psql_scan_slash_option(scan_state,
1709 									  OT_NORMAL, NULL, true);
1710 
1711 		if (strcmp(cmd + 3, "export") == 0)
1712 		{
1713 			if (!opt2)
1714 			{
1715 				pg_log_error("\\%s: missing required argument", cmd);
1716 				success = false;
1717 			}
1718 			else
1719 			{
1720 				expand_tilde(&opt2);
1721 				success = do_lo_export(opt1, opt2);
1722 			}
1723 		}
1724 
1725 		else if (strcmp(cmd + 3, "import") == 0)
1726 		{
1727 			if (!opt1)
1728 			{
1729 				pg_log_error("\\%s: missing required argument", cmd);
1730 				success = false;
1731 			}
1732 			else
1733 			{
1734 				expand_tilde(&opt1);
1735 				success = do_lo_import(opt1, opt2);
1736 			}
1737 		}
1738 
1739 		else if (strcmp(cmd + 3, "list") == 0)
1740 			success = do_lo_list();
1741 
1742 		else if (strcmp(cmd + 3, "unlink") == 0)
1743 		{
1744 			if (!opt1)
1745 			{
1746 				pg_log_error("\\%s: missing required argument", cmd);
1747 				success = false;
1748 			}
1749 			else
1750 				success = do_lo_unlink(opt1);
1751 		}
1752 
1753 		else
1754 			status = PSQL_CMD_UNKNOWN;
1755 
1756 		free(opt1);
1757 		free(opt2);
1758 	}
1759 	else
1760 		ignore_slash_options(scan_state);
1761 
1762 	if (!success)
1763 		status = PSQL_CMD_ERROR;
1764 
1765 	return status;
1766 }
1767 
1768 /*
1769  * \o -- set query output
1770  */
1771 static backslashResult
exec_command_out(PsqlScanState scan_state,bool active_branch)1772 exec_command_out(PsqlScanState scan_state, bool active_branch)
1773 {
1774 	bool		success = true;
1775 
1776 	if (active_branch)
1777 	{
1778 		char	   *fname = psql_scan_slash_option(scan_state,
1779 												   OT_FILEPIPE, NULL, true);
1780 
1781 		expand_tilde(&fname);
1782 		success = setQFout(fname);
1783 		free(fname);
1784 	}
1785 	else
1786 		ignore_slash_filepipe(scan_state);
1787 
1788 	return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
1789 }
1790 
1791 /*
1792  * \p -- print the current query buffer
1793  */
1794 static backslashResult
exec_command_print(PsqlScanState scan_state,bool active_branch,PQExpBuffer query_buf,PQExpBuffer previous_buf)1795 exec_command_print(PsqlScanState scan_state, bool active_branch,
1796 				   PQExpBuffer query_buf, PQExpBuffer previous_buf)
1797 {
1798 	if (active_branch)
1799 	{
1800 		/*
1801 		 * We want to print the same thing \g would execute, but not to change
1802 		 * the query buffer state; so we can't use copy_previous_query().
1803 		 * Also, beware of possibility that buffer pointers are NULL.
1804 		 */
1805 		if (query_buf && query_buf->len > 0)
1806 			puts(query_buf->data);
1807 		else if (previous_buf && previous_buf->len > 0)
1808 			puts(previous_buf->data);
1809 		else if (!pset.quiet)
1810 			puts(_("Query buffer is empty."));
1811 		fflush(stdout);
1812 	}
1813 
1814 	return PSQL_CMD_SKIP_LINE;
1815 }
1816 
1817 /*
1818  * \password -- set user password
1819  */
1820 static backslashResult
exec_command_password(PsqlScanState scan_state,bool active_branch)1821 exec_command_password(PsqlScanState scan_state, bool active_branch)
1822 {
1823 	bool		success = true;
1824 
1825 	if (active_branch)
1826 	{
1827 		char	   *opt0 = psql_scan_slash_option(scan_state,
1828 												  OT_SQLID, NULL, true);
1829 		char		pw1[100];
1830 		char		pw2[100];
1831 
1832 		simple_prompt("Enter new password: ", pw1, sizeof(pw1), false);
1833 		simple_prompt("Enter it again: ", pw2, sizeof(pw2), false);
1834 
1835 		if (strcmp(pw1, pw2) != 0)
1836 		{
1837 			pg_log_error("Passwords didn't match.");
1838 			success = false;
1839 		}
1840 		else
1841 		{
1842 			char	   *user;
1843 			char	   *encrypted_password;
1844 
1845 			if (opt0)
1846 				user = opt0;
1847 			else
1848 				user = PQuser(pset.db);
1849 
1850 			encrypted_password = PQencryptPasswordConn(pset.db, pw1, user, NULL);
1851 
1852 			if (!encrypted_password)
1853 			{
1854 				pg_log_info("%s", PQerrorMessage(pset.db));
1855 				success = false;
1856 			}
1857 			else
1858 			{
1859 				PQExpBufferData buf;
1860 				PGresult   *res;
1861 
1862 				initPQExpBuffer(&buf);
1863 				printfPQExpBuffer(&buf, "ALTER USER %s PASSWORD ",
1864 								  fmtId(user));
1865 				appendStringLiteralConn(&buf, encrypted_password, pset.db);
1866 				res = PSQLexec(buf.data);
1867 				termPQExpBuffer(&buf);
1868 				if (!res)
1869 					success = false;
1870 				else
1871 					PQclear(res);
1872 				PQfreemem(encrypted_password);
1873 			}
1874 		}
1875 
1876 		if (opt0)
1877 			free(opt0);
1878 	}
1879 	else
1880 		ignore_slash_options(scan_state);
1881 
1882 	return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
1883 }
1884 
1885 /*
1886  * \prompt -- prompt and set variable
1887  */
1888 static backslashResult
exec_command_prompt(PsqlScanState scan_state,bool active_branch,const char * cmd)1889 exec_command_prompt(PsqlScanState scan_state, bool active_branch,
1890 					const char *cmd)
1891 {
1892 	bool		success = true;
1893 
1894 	if (active_branch)
1895 	{
1896 		char	   *opt,
1897 				   *prompt_text = NULL;
1898 		char	   *arg1,
1899 				   *arg2;
1900 
1901 		arg1 = psql_scan_slash_option(scan_state, OT_NORMAL, NULL, false);
1902 		arg2 = psql_scan_slash_option(scan_state, OT_NORMAL, NULL, false);
1903 
1904 		if (!arg1)
1905 		{
1906 			pg_log_error("\\%s: missing required argument", cmd);
1907 			success = false;
1908 		}
1909 		else
1910 		{
1911 			char	   *result;
1912 
1913 			if (arg2)
1914 			{
1915 				prompt_text = arg1;
1916 				opt = arg2;
1917 			}
1918 			else
1919 				opt = arg1;
1920 
1921 			if (!pset.inputfile)
1922 			{
1923 				result = (char *) pg_malloc(4096);
1924 				simple_prompt(prompt_text, result, 4096, true);
1925 			}
1926 			else
1927 			{
1928 				if (prompt_text)
1929 				{
1930 					fputs(prompt_text, stdout);
1931 					fflush(stdout);
1932 				}
1933 				result = gets_fromFile(stdin);
1934 				if (!result)
1935 				{
1936 					pg_log_error("\\%s: could not read value for variable",
1937 								 cmd);
1938 					success = false;
1939 				}
1940 			}
1941 
1942 			if (result &&
1943 				!SetVariable(pset.vars, opt, result))
1944 				success = false;
1945 
1946 			if (result)
1947 				free(result);
1948 			if (prompt_text)
1949 				free(prompt_text);
1950 			free(opt);
1951 		}
1952 	}
1953 	else
1954 		ignore_slash_options(scan_state);
1955 
1956 	return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
1957 }
1958 
1959 /*
1960  * \pset -- set printing parameters
1961  */
1962 static backslashResult
exec_command_pset(PsqlScanState scan_state,bool active_branch)1963 exec_command_pset(PsqlScanState scan_state, bool active_branch)
1964 {
1965 	bool		success = true;
1966 
1967 	if (active_branch)
1968 	{
1969 		char	   *opt0 = psql_scan_slash_option(scan_state,
1970 												  OT_NORMAL, NULL, false);
1971 		char	   *opt1 = psql_scan_slash_option(scan_state,
1972 												  OT_NORMAL, NULL, false);
1973 
1974 		if (!opt0)
1975 		{
1976 			/* list all variables */
1977 
1978 			int			i;
1979 			static const char *const my_list[] = {
1980 				"border", "columns", "csv_fieldsep", "expanded", "fieldsep",
1981 				"fieldsep_zero", "footer", "format", "linestyle", "null",
1982 				"numericlocale", "pager", "pager_min_lines",
1983 				"recordsep", "recordsep_zero",
1984 				"tableattr", "title", "tuples_only",
1985 				"unicode_border_linestyle",
1986 				"unicode_column_linestyle",
1987 				"unicode_header_linestyle",
1988 				NULL
1989 			};
1990 
1991 			for (i = 0; my_list[i] != NULL; i++)
1992 			{
1993 				char	   *val = pset_value_string(my_list[i], &pset.popt);
1994 
1995 				printf("%-24s %s\n", my_list[i], val);
1996 				free(val);
1997 			}
1998 
1999 			success = true;
2000 		}
2001 		else
2002 			success = do_pset(opt0, opt1, &pset.popt, pset.quiet);
2003 
2004 		free(opt0);
2005 		free(opt1);
2006 	}
2007 	else
2008 		ignore_slash_options(scan_state);
2009 
2010 	return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
2011 }
2012 
2013 /*
2014  * \q or \quit -- exit psql
2015  */
2016 static backslashResult
exec_command_quit(PsqlScanState scan_state,bool active_branch)2017 exec_command_quit(PsqlScanState scan_state, bool active_branch)
2018 {
2019 	backslashResult status = PSQL_CMD_SKIP_LINE;
2020 
2021 	if (active_branch)
2022 		status = PSQL_CMD_TERMINATE;
2023 
2024 	return status;
2025 }
2026 
2027 /*
2028  * \r -- reset (clear) the query buffer
2029  */
2030 static backslashResult
exec_command_reset(PsqlScanState scan_state,bool active_branch,PQExpBuffer query_buf)2031 exec_command_reset(PsqlScanState scan_state, bool active_branch,
2032 				   PQExpBuffer query_buf)
2033 {
2034 	if (active_branch)
2035 	{
2036 		resetPQExpBuffer(query_buf);
2037 		psql_scan_reset(scan_state);
2038 		if (!pset.quiet)
2039 			puts(_("Query buffer reset (cleared)."));
2040 	}
2041 
2042 	return PSQL_CMD_SKIP_LINE;
2043 }
2044 
2045 /*
2046  * \s -- save history in a file or show it on the screen
2047  */
2048 static backslashResult
exec_command_s(PsqlScanState scan_state,bool active_branch)2049 exec_command_s(PsqlScanState scan_state, bool active_branch)
2050 {
2051 	bool		success = true;
2052 
2053 	if (active_branch)
2054 	{
2055 		char	   *fname = psql_scan_slash_option(scan_state,
2056 												   OT_NORMAL, NULL, true);
2057 
2058 		expand_tilde(&fname);
2059 		success = printHistory(fname, pset.popt.topt.pager);
2060 		if (success && !pset.quiet && fname)
2061 			printf(_("Wrote history to file \"%s\".\n"), fname);
2062 		if (!fname)
2063 			putchar('\n');
2064 		free(fname);
2065 	}
2066 	else
2067 		ignore_slash_options(scan_state);
2068 
2069 	return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
2070 }
2071 
2072 /*
2073  * \set -- set variable
2074  */
2075 static backslashResult
exec_command_set(PsqlScanState scan_state,bool active_branch)2076 exec_command_set(PsqlScanState scan_state, bool active_branch)
2077 {
2078 	bool		success = true;
2079 
2080 	if (active_branch)
2081 	{
2082 		char	   *opt0 = psql_scan_slash_option(scan_state,
2083 												  OT_NORMAL, NULL, false);
2084 
2085 		if (!opt0)
2086 		{
2087 			/* list all variables */
2088 			PrintVariables(pset.vars);
2089 			success = true;
2090 		}
2091 		else
2092 		{
2093 			/*
2094 			 * Set variable to the concatenation of the arguments.
2095 			 */
2096 			char	   *newval;
2097 			char	   *opt;
2098 
2099 			opt = psql_scan_slash_option(scan_state,
2100 										 OT_NORMAL, NULL, false);
2101 			newval = pg_strdup(opt ? opt : "");
2102 			free(opt);
2103 
2104 			while ((opt = psql_scan_slash_option(scan_state,
2105 												 OT_NORMAL, NULL, false)))
2106 			{
2107 				newval = pg_realloc(newval, strlen(newval) + strlen(opt) + 1);
2108 				strcat(newval, opt);
2109 				free(opt);
2110 			}
2111 
2112 			if (!SetVariable(pset.vars, opt0, newval))
2113 				success = false;
2114 
2115 			free(newval);
2116 		}
2117 		free(opt0);
2118 	}
2119 	else
2120 		ignore_slash_options(scan_state);
2121 
2122 	return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
2123 }
2124 
2125 /*
2126  * \setenv -- set environment variable
2127  */
2128 static backslashResult
exec_command_setenv(PsqlScanState scan_state,bool active_branch,const char * cmd)2129 exec_command_setenv(PsqlScanState scan_state, bool active_branch,
2130 					const char *cmd)
2131 {
2132 	bool		success = true;
2133 
2134 	if (active_branch)
2135 	{
2136 		char	   *envvar = psql_scan_slash_option(scan_state,
2137 													OT_NORMAL, NULL, false);
2138 		char	   *envval = psql_scan_slash_option(scan_state,
2139 													OT_NORMAL, NULL, false);
2140 
2141 		if (!envvar)
2142 		{
2143 			pg_log_error("\\%s: missing required argument", cmd);
2144 			success = false;
2145 		}
2146 		else if (strchr(envvar, '=') != NULL)
2147 		{
2148 			pg_log_error("\\%s: environment variable name must not contain \"=\"",
2149 						 cmd);
2150 			success = false;
2151 		}
2152 		else if (!envval)
2153 		{
2154 			/* No argument - unset the environment variable */
2155 			unsetenv(envvar);
2156 			success = true;
2157 		}
2158 		else
2159 		{
2160 			/* Set variable to the value of the next argument */
2161 			char	   *newval;
2162 
2163 			newval = psprintf("%s=%s", envvar, envval);
2164 			putenv(newval);
2165 			success = true;
2166 
2167 			/*
2168 			 * Do not free newval here, it will screw up the environment if
2169 			 * you do. See putenv man page for details. That means we leak a
2170 			 * bit of memory here, but not enough to worry about.
2171 			 */
2172 		}
2173 		free(envvar);
2174 		free(envval);
2175 	}
2176 	else
2177 		ignore_slash_options(scan_state);
2178 
2179 	return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
2180 }
2181 
2182 /*
2183  * \sf/\sv -- show a function/view's source code
2184  */
2185 static backslashResult
exec_command_sf_sv(PsqlScanState scan_state,bool active_branch,const char * cmd,bool is_func)2186 exec_command_sf_sv(PsqlScanState scan_state, bool active_branch,
2187 				   const char *cmd, bool is_func)
2188 {
2189 	backslashResult status = PSQL_CMD_SKIP_LINE;
2190 
2191 	if (active_branch)
2192 	{
2193 		bool		show_linenumbers = (strchr(cmd, '+') != NULL);
2194 		PQExpBuffer buf;
2195 		char	   *obj_desc;
2196 		Oid			obj_oid = InvalidOid;
2197 		EditableObjectType eot = is_func ? EditableFunction : EditableView;
2198 
2199 		buf = createPQExpBuffer();
2200 		obj_desc = psql_scan_slash_option(scan_state,
2201 										  OT_WHOLE_LINE, NULL, true);
2202 		if (pset.sversion < (is_func ? 80400 : 70400))
2203 		{
2204 			char		sverbuf[32];
2205 
2206 			formatPGVersionNumber(pset.sversion, false,
2207 								  sverbuf, sizeof(sverbuf));
2208 			if (is_func)
2209 				pg_log_error("The server (version %s) does not support showing function source.",
2210 							 sverbuf);
2211 			else
2212 				pg_log_error("The server (version %s) does not support showing view definitions.",
2213 							 sverbuf);
2214 			status = PSQL_CMD_ERROR;
2215 		}
2216 		else if (!obj_desc)
2217 		{
2218 			if (is_func)
2219 				pg_log_error("function name is required");
2220 			else
2221 				pg_log_error("view name is required");
2222 			status = PSQL_CMD_ERROR;
2223 		}
2224 		else if (!lookup_object_oid(eot, obj_desc, &obj_oid))
2225 		{
2226 			/* error already reported */
2227 			status = PSQL_CMD_ERROR;
2228 		}
2229 		else if (!get_create_object_cmd(eot, obj_oid, buf))
2230 		{
2231 			/* error already reported */
2232 			status = PSQL_CMD_ERROR;
2233 		}
2234 		else
2235 		{
2236 			FILE	   *output;
2237 			bool		is_pager;
2238 
2239 			/* Select output stream: stdout, pager, or file */
2240 			if (pset.queryFout == stdout)
2241 			{
2242 				/* count lines in function to see if pager is needed */
2243 				int			lineno = count_lines_in_buf(buf);
2244 
2245 				output = PageOutput(lineno, &(pset.popt.topt));
2246 				is_pager = true;
2247 			}
2248 			else
2249 			{
2250 				/* use previously set output file, without pager */
2251 				output = pset.queryFout;
2252 				is_pager = false;
2253 			}
2254 
2255 			if (show_linenumbers)
2256 			{
2257 				/*
2258 				 * For functions, lineno "1" should correspond to the first
2259 				 * line of the function body.  We expect that
2260 				 * pg_get_functiondef() will emit that on a line beginning
2261 				 * with "AS ", and that there can be no such line before the
2262 				 * real start of the function body.
2263 				 */
2264 				print_with_linenumbers(output, buf->data,
2265 									   is_func ? "AS " : NULL);
2266 			}
2267 			else
2268 			{
2269 				/* just send the definition to output */
2270 				fputs(buf->data, output);
2271 			}
2272 
2273 			if (is_pager)
2274 				ClosePager(output);
2275 		}
2276 
2277 		if (obj_desc)
2278 			free(obj_desc);
2279 		destroyPQExpBuffer(buf);
2280 	}
2281 	else
2282 		ignore_slash_whole_line(scan_state);
2283 
2284 	return status;
2285 }
2286 
2287 /*
2288  * \t -- turn off table headers and row count
2289  */
2290 static backslashResult
exec_command_t(PsqlScanState scan_state,bool active_branch)2291 exec_command_t(PsqlScanState scan_state, bool active_branch)
2292 {
2293 	bool		success = true;
2294 
2295 	if (active_branch)
2296 	{
2297 		char	   *opt = psql_scan_slash_option(scan_state,
2298 												 OT_NORMAL, NULL, true);
2299 
2300 		success = do_pset("tuples_only", opt, &pset.popt, pset.quiet);
2301 		free(opt);
2302 	}
2303 	else
2304 		ignore_slash_options(scan_state);
2305 
2306 	return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
2307 }
2308 
2309 /*
2310  * \T -- define html <table ...> attributes
2311  */
2312 static backslashResult
exec_command_T(PsqlScanState scan_state,bool active_branch)2313 exec_command_T(PsqlScanState scan_state, bool active_branch)
2314 {
2315 	bool		success = true;
2316 
2317 	if (active_branch)
2318 	{
2319 		char	   *value = psql_scan_slash_option(scan_state,
2320 												   OT_NORMAL, NULL, false);
2321 
2322 		success = do_pset("tableattr", value, &pset.popt, pset.quiet);
2323 		free(value);
2324 	}
2325 	else
2326 		ignore_slash_options(scan_state);
2327 
2328 	return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
2329 }
2330 
2331 /*
2332  * \timing -- enable/disable timing of queries
2333  */
2334 static backslashResult
exec_command_timing(PsqlScanState scan_state,bool active_branch)2335 exec_command_timing(PsqlScanState scan_state, bool active_branch)
2336 {
2337 	bool		success = true;
2338 
2339 	if (active_branch)
2340 	{
2341 		char	   *opt = psql_scan_slash_option(scan_state,
2342 												 OT_NORMAL, NULL, false);
2343 
2344 		if (opt)
2345 			success = ParseVariableBool(opt, "\\timing", &pset.timing);
2346 		else
2347 			pset.timing = !pset.timing;
2348 		if (!pset.quiet)
2349 		{
2350 			if (pset.timing)
2351 				puts(_("Timing is on."));
2352 			else
2353 				puts(_("Timing is off."));
2354 		}
2355 		free(opt);
2356 	}
2357 	else
2358 		ignore_slash_options(scan_state);
2359 
2360 	return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
2361 }
2362 
2363 /*
2364  * \unset -- unset variable
2365  */
2366 static backslashResult
exec_command_unset(PsqlScanState scan_state,bool active_branch,const char * cmd)2367 exec_command_unset(PsqlScanState scan_state, bool active_branch,
2368 				   const char *cmd)
2369 {
2370 	bool		success = true;
2371 
2372 	if (active_branch)
2373 	{
2374 		char	   *opt = psql_scan_slash_option(scan_state,
2375 												 OT_NORMAL, NULL, false);
2376 
2377 		if (!opt)
2378 		{
2379 			pg_log_error("\\%s: missing required argument", cmd);
2380 			success = false;
2381 		}
2382 		else if (!SetVariable(pset.vars, opt, NULL))
2383 			success = false;
2384 
2385 		free(opt);
2386 	}
2387 	else
2388 		ignore_slash_options(scan_state);
2389 
2390 	return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
2391 }
2392 
2393 /*
2394  * \w -- write query buffer to file
2395  */
2396 static backslashResult
exec_command_write(PsqlScanState scan_state,bool active_branch,const char * cmd,PQExpBuffer query_buf,PQExpBuffer previous_buf)2397 exec_command_write(PsqlScanState scan_state, bool active_branch,
2398 				   const char *cmd,
2399 				   PQExpBuffer query_buf, PQExpBuffer previous_buf)
2400 {
2401 	backslashResult status = PSQL_CMD_SKIP_LINE;
2402 
2403 	if (active_branch)
2404 	{
2405 		char	   *fname = psql_scan_slash_option(scan_state,
2406 												   OT_FILEPIPE, NULL, true);
2407 		FILE	   *fd = NULL;
2408 		bool		is_pipe = false;
2409 
2410 		if (!query_buf)
2411 		{
2412 			pg_log_error("no query buffer");
2413 			status = PSQL_CMD_ERROR;
2414 		}
2415 		else
2416 		{
2417 			if (!fname)
2418 			{
2419 				pg_log_error("\\%s: missing required argument", cmd);
2420 				status = PSQL_CMD_ERROR;
2421 			}
2422 			else
2423 			{
2424 				expand_tilde(&fname);
2425 				if (fname[0] == '|')
2426 				{
2427 					is_pipe = true;
2428 					disable_sigpipe_trap();
2429 					fd = popen(&fname[1], "w");
2430 				}
2431 				else
2432 				{
2433 					canonicalize_path(fname);
2434 					fd = fopen(fname, "w");
2435 				}
2436 				if (!fd)
2437 				{
2438 					pg_log_error("%s: %m", fname);
2439 					status = PSQL_CMD_ERROR;
2440 				}
2441 			}
2442 		}
2443 
2444 		if (fd)
2445 		{
2446 			int			result;
2447 
2448 			/*
2449 			 * We want to print the same thing \g would execute, but not to
2450 			 * change the query buffer state; so we can't use
2451 			 * copy_previous_query().  Also, beware of possibility that buffer
2452 			 * pointers are NULL.
2453 			 */
2454 			if (query_buf && query_buf->len > 0)
2455 				fprintf(fd, "%s\n", query_buf->data);
2456 			else if (previous_buf && previous_buf->len > 0)
2457 				fprintf(fd, "%s\n", previous_buf->data);
2458 
2459 			if (is_pipe)
2460 				result = pclose(fd);
2461 			else
2462 				result = fclose(fd);
2463 
2464 			if (result == EOF)
2465 			{
2466 				pg_log_error("%s: %m", fname);
2467 				status = PSQL_CMD_ERROR;
2468 			}
2469 		}
2470 
2471 		if (is_pipe)
2472 			restore_sigpipe_trap();
2473 
2474 		free(fname);
2475 	}
2476 	else
2477 		ignore_slash_filepipe(scan_state);
2478 
2479 	return status;
2480 }
2481 
2482 /*
2483  * \watch -- execute a query every N seconds
2484  */
2485 static backslashResult
exec_command_watch(PsqlScanState scan_state,bool active_branch,PQExpBuffer query_buf,PQExpBuffer previous_buf)2486 exec_command_watch(PsqlScanState scan_state, bool active_branch,
2487 				   PQExpBuffer query_buf, PQExpBuffer previous_buf)
2488 {
2489 	bool		success = true;
2490 
2491 	if (active_branch)
2492 	{
2493 		char	   *opt = psql_scan_slash_option(scan_state,
2494 												 OT_NORMAL, NULL, true);
2495 		double		sleep = 2;
2496 
2497 		/* Convert optional sleep-length argument */
2498 		if (opt)
2499 		{
2500 			sleep = strtod(opt, NULL);
2501 			if (sleep <= 0)
2502 				sleep = 1;
2503 			free(opt);
2504 		}
2505 
2506 		/* If query_buf is empty, recall and execute previous query */
2507 		copy_previous_query(query_buf, previous_buf);
2508 
2509 		success = do_watch(query_buf, sleep);
2510 
2511 		/* Reset the query buffer as though for \r */
2512 		resetPQExpBuffer(query_buf);
2513 		psql_scan_reset(scan_state);
2514 	}
2515 	else
2516 		ignore_slash_options(scan_state);
2517 
2518 	return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
2519 }
2520 
2521 /*
2522  * \x -- set or toggle expanded table representation
2523  */
2524 static backslashResult
exec_command_x(PsqlScanState scan_state,bool active_branch)2525 exec_command_x(PsqlScanState scan_state, bool active_branch)
2526 {
2527 	bool		success = true;
2528 
2529 	if (active_branch)
2530 	{
2531 		char	   *opt = psql_scan_slash_option(scan_state,
2532 												 OT_NORMAL, NULL, true);
2533 
2534 		success = do_pset("expanded", opt, &pset.popt, pset.quiet);
2535 		free(opt);
2536 	}
2537 	else
2538 		ignore_slash_options(scan_state);
2539 
2540 	return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
2541 }
2542 
2543 /*
2544  * \z -- list table privileges (equivalent to \dp)
2545  */
2546 static backslashResult
exec_command_z(PsqlScanState scan_state,bool active_branch)2547 exec_command_z(PsqlScanState scan_state, bool active_branch)
2548 {
2549 	bool		success = true;
2550 
2551 	if (active_branch)
2552 	{
2553 		char	   *pattern = psql_scan_slash_option(scan_state,
2554 													 OT_NORMAL, NULL, true);
2555 
2556 		success = permissionsList(pattern);
2557 		if (pattern)
2558 			free(pattern);
2559 	}
2560 	else
2561 		ignore_slash_options(scan_state);
2562 
2563 	return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
2564 }
2565 
2566 /*
2567  * \! -- execute shell command
2568  */
2569 static backslashResult
exec_command_shell_escape(PsqlScanState scan_state,bool active_branch)2570 exec_command_shell_escape(PsqlScanState scan_state, bool active_branch)
2571 {
2572 	bool		success = true;
2573 
2574 	if (active_branch)
2575 	{
2576 		char	   *opt = psql_scan_slash_option(scan_state,
2577 												 OT_WHOLE_LINE, NULL, false);
2578 
2579 		success = do_shell(opt);
2580 		free(opt);
2581 	}
2582 	else
2583 		ignore_slash_whole_line(scan_state);
2584 
2585 	return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
2586 }
2587 
2588 /*
2589  * \? -- print help about backslash commands
2590  */
2591 static backslashResult
exec_command_slash_command_help(PsqlScanState scan_state,bool active_branch)2592 exec_command_slash_command_help(PsqlScanState scan_state, bool active_branch)
2593 {
2594 	if (active_branch)
2595 	{
2596 		char	   *opt0 = psql_scan_slash_option(scan_state,
2597 												  OT_NORMAL, NULL, false);
2598 
2599 		if (!opt0 || strcmp(opt0, "commands") == 0)
2600 			slashUsage(pset.popt.topt.pager);
2601 		else if (strcmp(opt0, "options") == 0)
2602 			usage(pset.popt.topt.pager);
2603 		else if (strcmp(opt0, "variables") == 0)
2604 			helpVariables(pset.popt.topt.pager);
2605 		else
2606 			slashUsage(pset.popt.topt.pager);
2607 
2608 		if (opt0)
2609 			free(opt0);
2610 	}
2611 	else
2612 		ignore_slash_options(scan_state);
2613 
2614 	return PSQL_CMD_SKIP_LINE;
2615 }
2616 
2617 
2618 /*
2619  * Read and interpret an argument to the \connect slash command.
2620  *
2621  * Returns a malloc'd string, or NULL if no/empty argument.
2622  */
2623 static char *
read_connect_arg(PsqlScanState scan_state)2624 read_connect_arg(PsqlScanState scan_state)
2625 {
2626 	char	   *result;
2627 	char		quote;
2628 
2629 	/*
2630 	 * Ideally we should treat the arguments as SQL identifiers.  But for
2631 	 * backwards compatibility with 7.2 and older pg_dump files, we have to
2632 	 * take unquoted arguments verbatim (don't downcase them). For now,
2633 	 * double-quoted arguments may be stripped of double quotes (as if SQL
2634 	 * identifiers).  By 7.4 or so, pg_dump files can be expected to
2635 	 * double-quote all mixed-case \connect arguments, and then we can get rid
2636 	 * of OT_SQLIDHACK.
2637 	 */
2638 	result = psql_scan_slash_option(scan_state, OT_SQLIDHACK, &quote, true);
2639 
2640 	if (!result)
2641 		return NULL;
2642 
2643 	if (quote)
2644 		return result;
2645 
2646 	if (*result == '\0' || strcmp(result, "-") == 0)
2647 	{
2648 		free(result);
2649 		return NULL;
2650 	}
2651 
2652 	return result;
2653 }
2654 
2655 /*
2656  * Read a boolean expression, return it as a PQExpBuffer string.
2657  *
2658  * Note: anything more or less than one token will certainly fail to be
2659  * parsed by ParseVariableBool, so we don't worry about complaining here.
2660  * This routine's return data structure will need to be rethought anyway
2661  * to support likely future extensions such as "\if defined VARNAME".
2662  */
2663 static PQExpBuffer
gather_boolean_expression(PsqlScanState scan_state)2664 gather_boolean_expression(PsqlScanState scan_state)
2665 {
2666 	PQExpBuffer exp_buf = createPQExpBuffer();
2667 	int			num_options = 0;
2668 	char	   *value;
2669 
2670 	/* collect all arguments for the conditional command into exp_buf */
2671 	while ((value = psql_scan_slash_option(scan_state,
2672 										   OT_NORMAL, NULL, false)) != NULL)
2673 	{
2674 		/* add spaces between tokens */
2675 		if (num_options > 0)
2676 			appendPQExpBufferChar(exp_buf, ' ');
2677 		appendPQExpBufferStr(exp_buf, value);
2678 		num_options++;
2679 		free(value);
2680 	}
2681 
2682 	return exp_buf;
2683 }
2684 
2685 /*
2686  * Read a boolean expression, return true if the expression
2687  * was a valid boolean expression that evaluated to true.
2688  * Otherwise return false.
2689  *
2690  * Note: conditional stack's top state must be active, else lexer will
2691  * fail to expand variables and backticks.
2692  */
2693 static bool
is_true_boolean_expression(PsqlScanState scan_state,const char * name)2694 is_true_boolean_expression(PsqlScanState scan_state, const char *name)
2695 {
2696 	PQExpBuffer buf = gather_boolean_expression(scan_state);
2697 	bool		value = false;
2698 	bool		success = ParseVariableBool(buf->data, name, &value);
2699 
2700 	destroyPQExpBuffer(buf);
2701 	return success && value;
2702 }
2703 
2704 /*
2705  * Read a boolean expression, but do nothing with it.
2706  *
2707  * Note: conditional stack's top state must be INACTIVE, else lexer will
2708  * expand variables and backticks, which we do not want here.
2709  */
2710 static void
ignore_boolean_expression(PsqlScanState scan_state)2711 ignore_boolean_expression(PsqlScanState scan_state)
2712 {
2713 	PQExpBuffer buf = gather_boolean_expression(scan_state);
2714 
2715 	destroyPQExpBuffer(buf);
2716 }
2717 
2718 /*
2719  * Read and discard "normal" slash command options.
2720  *
2721  * This should be used for inactive-branch processing of any slash command
2722  * that eats one or more OT_NORMAL, OT_SQLID, or OT_SQLIDHACK parameters.
2723  * We don't need to worry about exactly how many it would eat, since the
2724  * cleanup logic in HandleSlashCmds would silently discard any extras anyway.
2725  */
2726 static void
ignore_slash_options(PsqlScanState scan_state)2727 ignore_slash_options(PsqlScanState scan_state)
2728 {
2729 	char	   *arg;
2730 
2731 	while ((arg = psql_scan_slash_option(scan_state,
2732 										 OT_NORMAL, NULL, false)) != NULL)
2733 		free(arg);
2734 }
2735 
2736 /*
2737  * Read and discard FILEPIPE slash command argument.
2738  *
2739  * This *MUST* be used for inactive-branch processing of any slash command
2740  * that takes an OT_FILEPIPE option.  Otherwise we might consume a different
2741  * amount of option text in active and inactive cases.
2742  */
2743 static void
ignore_slash_filepipe(PsqlScanState scan_state)2744 ignore_slash_filepipe(PsqlScanState scan_state)
2745 {
2746 	char	   *arg = psql_scan_slash_option(scan_state,
2747 											 OT_FILEPIPE, NULL, false);
2748 
2749 	if (arg)
2750 		free(arg);
2751 }
2752 
2753 /*
2754  * Read and discard whole-line slash command argument.
2755  *
2756  * This *MUST* be used for inactive-branch processing of any slash command
2757  * that takes an OT_WHOLE_LINE option.  Otherwise we might consume a different
2758  * amount of option text in active and inactive cases.
2759  */
2760 static void
ignore_slash_whole_line(PsqlScanState scan_state)2761 ignore_slash_whole_line(PsqlScanState scan_state)
2762 {
2763 	char	   *arg = psql_scan_slash_option(scan_state,
2764 											 OT_WHOLE_LINE, NULL, false);
2765 
2766 	if (arg)
2767 		free(arg);
2768 }
2769 
2770 /*
2771  * Return true if the command given is a branching command.
2772  */
2773 static bool
is_branching_command(const char * cmd)2774 is_branching_command(const char *cmd)
2775 {
2776 	return (strcmp(cmd, "if") == 0 ||
2777 			strcmp(cmd, "elif") == 0 ||
2778 			strcmp(cmd, "else") == 0 ||
2779 			strcmp(cmd, "endif") == 0);
2780 }
2781 
2782 /*
2783  * Prepare to possibly restore query buffer to its current state
2784  * (cf. discard_query_text).
2785  *
2786  * We need to remember the length of the query buffer, and the lexer's
2787  * notion of the parenthesis nesting depth.
2788  */
2789 static void
save_query_text_state(PsqlScanState scan_state,ConditionalStack cstack,PQExpBuffer query_buf)2790 save_query_text_state(PsqlScanState scan_state, ConditionalStack cstack,
2791 					  PQExpBuffer query_buf)
2792 {
2793 	if (query_buf)
2794 		conditional_stack_set_query_len(cstack, query_buf->len);
2795 	conditional_stack_set_paren_depth(cstack,
2796 									  psql_scan_get_paren_depth(scan_state));
2797 }
2798 
2799 /*
2800  * Discard any query text absorbed during an inactive conditional branch.
2801  *
2802  * We must discard data that was appended to query_buf during an inactive
2803  * \if branch.  We don't have to do anything there if there's no query_buf.
2804  *
2805  * Also, reset the lexer state to the same paren depth there was before.
2806  * (The rest of its state doesn't need attention, since we could not be
2807  * inside a comment or literal or partial token.)
2808  */
2809 static void
discard_query_text(PsqlScanState scan_state,ConditionalStack cstack,PQExpBuffer query_buf)2810 discard_query_text(PsqlScanState scan_state, ConditionalStack cstack,
2811 				   PQExpBuffer query_buf)
2812 {
2813 	if (query_buf)
2814 	{
2815 		int			new_len = conditional_stack_get_query_len(cstack);
2816 
2817 		Assert(new_len >= 0 && new_len <= query_buf->len);
2818 		query_buf->len = new_len;
2819 		query_buf->data[new_len] = '\0';
2820 	}
2821 	psql_scan_set_paren_depth(scan_state,
2822 							  conditional_stack_get_paren_depth(cstack));
2823 }
2824 
2825 /*
2826  * If query_buf is empty, copy previous_buf into it.
2827  *
2828  * This is used by various slash commands for which re-execution of a
2829  * previous query is a common usage.  For convenience, we allow the
2830  * case of query_buf == NULL (and do nothing).
2831  */
2832 static void
copy_previous_query(PQExpBuffer query_buf,PQExpBuffer previous_buf)2833 copy_previous_query(PQExpBuffer query_buf, PQExpBuffer previous_buf)
2834 {
2835 	if (query_buf && query_buf->len == 0)
2836 		appendPQExpBufferStr(query_buf, previous_buf->data);
2837 }
2838 
2839 /*
2840  * Ask the user for a password; 'username' is the username the
2841  * password is for, if one has been explicitly specified. Returns a
2842  * malloc'd string.
2843  */
2844 static char *
prompt_for_password(const char * username)2845 prompt_for_password(const char *username)
2846 {
2847 	char		buf[100];
2848 
2849 	if (username == NULL || username[0] == '\0')
2850 		simple_prompt("Password: ", buf, sizeof(buf), false);
2851 	else
2852 	{
2853 		char	   *prompt_text;
2854 
2855 		prompt_text = psprintf(_("Password for user %s: "), username);
2856 		simple_prompt(prompt_text, buf, sizeof(buf), false);
2857 		free(prompt_text);
2858 	}
2859 	return pg_strdup(buf);
2860 }
2861 
2862 static bool
param_is_newly_set(const char * old_val,const char * new_val)2863 param_is_newly_set(const char *old_val, const char *new_val)
2864 {
2865 	if (new_val == NULL)
2866 		return false;
2867 
2868 	if (old_val == NULL || strcmp(old_val, new_val) != 0)
2869 		return true;
2870 
2871 	return false;
2872 }
2873 
2874 /*
2875  * do_connect -- handler for \connect
2876  *
2877  * Connects to a database with given parameters. Absent an established
2878  * connection, all parameters are required. Given -reuse-previous=off or a
2879  * connection string without -reuse-previous=on, NULL values will pass through
2880  * to PQconnectdbParams(), so the libpq defaults will be used. Otherwise, NULL
2881  * values will be replaced with the ones in the current connection.
2882  *
2883  * In interactive mode, if connection fails with the given parameters,
2884  * the old connection will be kept.
2885  */
2886 static bool
do_connect(enum trivalue reuse_previous_specification,char * dbname,char * user,char * host,char * port)2887 do_connect(enum trivalue reuse_previous_specification,
2888 		   char *dbname, char *user, char *host, char *port)
2889 {
2890 	PGconn	   *o_conn = pset.db,
2891 			   *n_conn = NULL;
2892 	PQconninfoOption *cinfo;
2893 	int			nconnopts = 0;
2894 	bool		same_host = false;
2895 	char	   *password = NULL;
2896 	char	   *client_encoding;
2897 	bool		success = true;
2898 	bool		keep_password = true;
2899 	bool		has_connection_string;
2900 	bool		reuse_previous;
2901 
2902 	if (!o_conn && (!dbname || !user || !host || !port))
2903 	{
2904 		/*
2905 		 * We don't know the supplied connection parameters and don't want to
2906 		 * connect to the wrong database by using defaults, so require all
2907 		 * parameters to be specified.
2908 		 */
2909 		pg_log_error("All connection parameters must be supplied because no "
2910 					 "database connection exists");
2911 		return false;
2912 	}
2913 
2914 	has_connection_string = dbname ?
2915 		recognized_connection_string(dbname) : false;
2916 	switch (reuse_previous_specification)
2917 	{
2918 		case TRI_YES:
2919 			reuse_previous = true;
2920 			break;
2921 		case TRI_NO:
2922 			reuse_previous = false;
2923 			break;
2924 		default:
2925 			reuse_previous = !has_connection_string;
2926 			break;
2927 	}
2928 
2929 	/* If the old connection does not exist, there is nothing to reuse. */
2930 	if (!o_conn)
2931 		reuse_previous = false;
2932 
2933 	/* Silently ignore arguments subsequent to a connection string. */
2934 	if (has_connection_string)
2935 	{
2936 		user = NULL;
2937 		host = NULL;
2938 		port = NULL;
2939 	}
2940 
2941 	/*
2942 	 * If we intend to re-use connection parameters, collect them out of the
2943 	 * old connection, then replace individual values as necessary. Otherwise,
2944 	 * obtain a PQconninfoOption array containing libpq's defaults, and modify
2945 	 * that.  Note this function assumes that PQconninfo, PQconndefaults, and
2946 	 * PQconninfoParse will all produce arrays containing the same options in
2947 	 * the same order.
2948 	 */
2949 	if (reuse_previous)
2950 		cinfo = PQconninfo(o_conn);
2951 	else
2952 		cinfo = PQconndefaults();
2953 
2954 	if (cinfo)
2955 	{
2956 		if (has_connection_string)
2957 		{
2958 			/* Parse the connstring and insert values into cinfo */
2959 			PQconninfoOption *replcinfo;
2960 			char	   *errmsg;
2961 
2962 			replcinfo = PQconninfoParse(dbname, &errmsg);
2963 			if (replcinfo)
2964 			{
2965 				PQconninfoOption *ci;
2966 				PQconninfoOption *replci;
2967 				bool		have_password = false;
2968 
2969 				for (ci = cinfo, replci = replcinfo;
2970 					 ci->keyword && replci->keyword;
2971 					 ci++, replci++)
2972 				{
2973 					Assert(strcmp(ci->keyword, replci->keyword) == 0);
2974 					/* Insert value from connstring if one was provided */
2975 					if (replci->val)
2976 					{
2977 						/*
2978 						 * We know that both val strings were allocated by
2979 						 * libpq, so the least messy way to avoid memory leaks
2980 						 * is to swap them.
2981 						 */
2982 						char	   *swap = replci->val;
2983 
2984 						replci->val = ci->val;
2985 						ci->val = swap;
2986 
2987 						/*
2988 						 * Check whether connstring provides options affecting
2989 						 * password re-use.  While any change in user, host,
2990 						 * hostaddr, or port causes us to ignore the old
2991 						 * connection's password, we don't force that for
2992 						 * dbname, since passwords aren't database-specific.
2993 						 */
2994 						if (replci->val == NULL ||
2995 							strcmp(ci->val, replci->val) != 0)
2996 						{
2997 							if (strcmp(replci->keyword, "user") == 0 ||
2998 								strcmp(replci->keyword, "host") == 0 ||
2999 								strcmp(replci->keyword, "hostaddr") == 0 ||
3000 								strcmp(replci->keyword, "port") == 0)
3001 								keep_password = false;
3002 						}
3003 						/* Also note whether connstring contains a password. */
3004 						if (strcmp(replci->keyword, "password") == 0)
3005 							have_password = true;
3006 					}
3007 					else if (!reuse_previous)
3008 					{
3009 						/*
3010 						 * When we have a connstring and are not re-using
3011 						 * parameters, swap *all* entries, even those not set
3012 						 * by the connstring.  This avoids absorbing
3013 						 * environment-dependent defaults from the result of
3014 						 * PQconndefaults().  We don't want to do that because
3015 						 * they'd override service-file entries if the
3016 						 * connstring specifies a service parameter, whereas
3017 						 * the priority should be the other way around.  libpq
3018 						 * can certainly recompute any defaults we don't pass
3019 						 * here.  (In this situation, it's a bit wasteful to
3020 						 * have called PQconndefaults() at all, but not doing
3021 						 * so would require yet another major code path here.)
3022 						 */
3023 						replci->val = ci->val;
3024 						ci->val = NULL;
3025 					}
3026 				}
3027 				Assert(ci->keyword == NULL && replci->keyword == NULL);
3028 
3029 				/* While here, determine how many option slots there are */
3030 				nconnopts = ci - cinfo;
3031 
3032 				PQconninfoFree(replcinfo);
3033 
3034 				/*
3035 				 * If the connstring contains a password, tell the loop below
3036 				 * that we may use it, regardless of other settings (i.e.,
3037 				 * cinfo's password is no longer an "old" password).
3038 				 */
3039 				if (have_password)
3040 					keep_password = true;
3041 
3042 				/* Don't let code below try to inject dbname into params. */
3043 				dbname = NULL;
3044 			}
3045 			else
3046 			{
3047 				/* PQconninfoParse failed */
3048 				if (errmsg)
3049 				{
3050 					pg_log_error("%s", errmsg);
3051 					PQfreemem(errmsg);
3052 				}
3053 				else
3054 					pg_log_error("out of memory");
3055 				success = false;
3056 			}
3057 		}
3058 		else
3059 		{
3060 			/*
3061 			 * If dbname isn't a connection string, then we'll inject it and
3062 			 * the other parameters into the keyword array below.  (We can't
3063 			 * easily insert them into the cinfo array because of memory
3064 			 * management issues: PQconninfoFree would misbehave on Windows.)
3065 			 * However, to avoid dependencies on the order in which parameters
3066 			 * appear in the array, make a preliminary scan to set
3067 			 * keep_password and same_host correctly.
3068 			 *
3069 			 * While any change in user, host, or port causes us to ignore the
3070 			 * old connection's password, we don't force that for dbname,
3071 			 * since passwords aren't database-specific.
3072 			 */
3073 			PQconninfoOption *ci;
3074 
3075 			for (ci = cinfo; ci->keyword; ci++)
3076 			{
3077 				if (user && strcmp(ci->keyword, "user") == 0)
3078 				{
3079 					if (!(ci->val && strcmp(user, ci->val) == 0))
3080 						keep_password = false;
3081 				}
3082 				else if (host && strcmp(ci->keyword, "host") == 0)
3083 				{
3084 					if (ci->val && strcmp(host, ci->val) == 0)
3085 						same_host = true;
3086 					else
3087 						keep_password = false;
3088 				}
3089 				else if (port && strcmp(ci->keyword, "port") == 0)
3090 				{
3091 					if (!(ci->val && strcmp(port, ci->val) == 0))
3092 						keep_password = false;
3093 				}
3094 			}
3095 
3096 			/* While here, determine how many option slots there are */
3097 			nconnopts = ci - cinfo;
3098 		}
3099 	}
3100 	else
3101 	{
3102 		/* We failed to create the cinfo structure */
3103 		pg_log_error("out of memory");
3104 		success = false;
3105 	}
3106 
3107 	/*
3108 	 * If the user asked to be prompted for a password, ask for one now. If
3109 	 * not, use the password from the old connection, provided the username
3110 	 * etc have not changed. Otherwise, try to connect without a password
3111 	 * first, and then ask for a password if needed.
3112 	 *
3113 	 * XXX: this behavior leads to spurious connection attempts recorded in
3114 	 * the postmaster's log.  But libpq offers no API that would let us obtain
3115 	 * a password and then continue with the first connection attempt.
3116 	 */
3117 	if (pset.getPassword == TRI_YES && success)
3118 	{
3119 		/*
3120 		 * If a connstring or URI is provided, we don't know which username
3121 		 * will be used, since we haven't dug that out of the connstring.
3122 		 * Don't risk issuing a misleading prompt.  As in startup.c, it does
3123 		 * not seem worth working harder, since this getPassword setting is
3124 		 * normally only used in noninteractive cases.
3125 		 */
3126 		password = prompt_for_password(has_connection_string ? NULL : user);
3127 	}
3128 
3129 	/*
3130 	 * Consider whether to force client_encoding to "auto" (overriding
3131 	 * anything in the connection string).  We do so if we have a terminal
3132 	 * connection and there is no PGCLIENTENCODING environment setting.
3133 	 */
3134 	if (pset.notty || getenv("PGCLIENTENCODING"))
3135 		client_encoding = NULL;
3136 	else
3137 		client_encoding = "auto";
3138 
3139 	/* Loop till we have a connection or fail, which we might've already */
3140 	while (success)
3141 	{
3142 		const char **keywords = pg_malloc((nconnopts + 1) * sizeof(*keywords));
3143 		const char **values = pg_malloc((nconnopts + 1) * sizeof(*values));
3144 		int			paramnum = 0;
3145 		PQconninfoOption *ci;
3146 
3147 		/*
3148 		 * Copy non-default settings into the PQconnectdbParams parameter
3149 		 * arrays; but inject any values specified old-style, as well as any
3150 		 * interactively-obtained password, and a couple of fields we want to
3151 		 * set forcibly.
3152 		 *
3153 		 * If you change this code, see also the initial-connection code in
3154 		 * main().
3155 		 */
3156 		for (ci = cinfo; ci->keyword; ci++)
3157 		{
3158 			keywords[paramnum] = ci->keyword;
3159 
3160 			if (dbname && strcmp(ci->keyword, "dbname") == 0)
3161 				values[paramnum++] = dbname;
3162 			else if (user && strcmp(ci->keyword, "user") == 0)
3163 				values[paramnum++] = user;
3164 			else if (host && strcmp(ci->keyword, "host") == 0)
3165 				values[paramnum++] = host;
3166 			else if (host && !same_host && strcmp(ci->keyword, "hostaddr") == 0)
3167 			{
3168 				/* If we're changing the host value, drop any old hostaddr */
3169 				values[paramnum++] = NULL;
3170 			}
3171 			else if (port && strcmp(ci->keyword, "port") == 0)
3172 				values[paramnum++] = port;
3173 			/* If !keep_password, we unconditionally drop old password */
3174 			else if ((password || !keep_password) &&
3175 					 strcmp(ci->keyword, "password") == 0)
3176 				values[paramnum++] = password;
3177 			else if (strcmp(ci->keyword, "fallback_application_name") == 0)
3178 				values[paramnum++] = pset.progname;
3179 			else if (client_encoding &&
3180 					 strcmp(ci->keyword, "client_encoding") == 0)
3181 				values[paramnum++] = client_encoding;
3182 			else if (ci->val)
3183 				values[paramnum++] = ci->val;
3184 			/* else, don't bother making libpq parse this keyword */
3185 		}
3186 		/* add array terminator */
3187 		keywords[paramnum] = NULL;
3188 		values[paramnum] = NULL;
3189 
3190 		/* Note we do not want libpq to re-expand the dbname parameter */
3191 		n_conn = PQconnectdbParams(keywords, values, false);
3192 
3193 		pg_free(keywords);
3194 		pg_free(values);
3195 
3196 		if (PQstatus(n_conn) == CONNECTION_OK)
3197 			break;
3198 
3199 		/*
3200 		 * Connection attempt failed; either retry the connection attempt with
3201 		 * a new password, or give up.
3202 		 */
3203 		if (!password && PQconnectionNeedsPassword(n_conn) && pset.getPassword != TRI_NO)
3204 		{
3205 			/*
3206 			 * Prompt for password using the username we actually connected
3207 			 * with --- it might've come out of "dbname" rather than "user".
3208 			 */
3209 			password = prompt_for_password(PQuser(n_conn));
3210 			PQfinish(n_conn);
3211 			n_conn = NULL;
3212 			continue;
3213 		}
3214 
3215 		/*
3216 		 * We'll report the error below ... unless n_conn is NULL, indicating
3217 		 * that libpq didn't have enough memory to make a PGconn.
3218 		 */
3219 		if (n_conn == NULL)
3220 			pg_log_error("out of memory");
3221 
3222 		success = false;
3223 	}							/* end retry loop */
3224 
3225 	/* Release locally allocated data, whether we succeeded or not */
3226 	if (password)
3227 		pg_free(password);
3228 	if (cinfo)
3229 		PQconninfoFree(cinfo);
3230 
3231 	if (!success)
3232 	{
3233 		/*
3234 		 * Failed to connect to the database. In interactive mode, keep the
3235 		 * previous connection to the DB; in scripting mode, close our
3236 		 * previous connection as well.
3237 		 */
3238 		if (pset.cur_cmd_interactive)
3239 		{
3240 			if (n_conn)
3241 			{
3242 				pg_log_info("%s", PQerrorMessage(n_conn));
3243 				PQfinish(n_conn);
3244 			}
3245 
3246 			/* pset.db is left unmodified */
3247 			if (o_conn)
3248 				pg_log_info("Previous connection kept");
3249 		}
3250 		else
3251 		{
3252 			if (n_conn)
3253 			{
3254 				pg_log_error("\\connect: %s", PQerrorMessage(n_conn));
3255 				PQfinish(n_conn);
3256 			}
3257 
3258 			if (o_conn)
3259 			{
3260 				/*
3261 				 * Transition to having no connection.  Keep this bit in sync
3262 				 * with CheckConnection().
3263 				 */
3264 				PQfinish(o_conn);
3265 				pset.db = NULL;
3266 				ResetCancelConn();
3267 				UnsyncVariables();
3268 			}
3269 		}
3270 
3271 		return false;
3272 	}
3273 
3274 	/*
3275 	 * Replace the old connection with the new one, and update
3276 	 * connection-dependent variables.  Keep the resynchronization logic in
3277 	 * sync with CheckConnection().
3278 	 */
3279 	PQsetNoticeProcessor(n_conn, NoticeProcessor, NULL);
3280 	pset.db = n_conn;
3281 	SyncVariables();
3282 	connection_warnings(false); /* Must be after SyncVariables */
3283 
3284 	/* Tell the user about the new connection */
3285 	if (!pset.quiet)
3286 	{
3287 		if (!o_conn ||
3288 			param_is_newly_set(PQhost(o_conn), PQhost(pset.db)) ||
3289 			param_is_newly_set(PQport(o_conn), PQport(pset.db)))
3290 		{
3291 			char	   *host = PQhost(pset.db);
3292 			char	   *hostaddr = PQhostaddr(pset.db);
3293 
3294 			/*
3295 			 * If the host is an absolute path, the connection is via socket
3296 			 * unless overridden by hostaddr
3297 			 */
3298 			if (is_absolute_path(host))
3299 			{
3300 				if (hostaddr && *hostaddr)
3301 					printf(_("You are now connected to database \"%s\" as user \"%s\" on address \"%s\" at port \"%s\".\n"),
3302 						   PQdb(pset.db), PQuser(pset.db), hostaddr, PQport(pset.db));
3303 				else
3304 					printf(_("You are now connected to database \"%s\" as user \"%s\" via socket in \"%s\" at port \"%s\".\n"),
3305 						   PQdb(pset.db), PQuser(pset.db), host, PQport(pset.db));
3306 			}
3307 			else
3308 			{
3309 				if (hostaddr && *hostaddr && strcmp(host, hostaddr) != 0)
3310 					printf(_("You are now connected to database \"%s\" as user \"%s\" on host \"%s\" (address \"%s\") at port \"%s\".\n"),
3311 						   PQdb(pset.db), PQuser(pset.db), host, hostaddr, PQport(pset.db));
3312 				else
3313 					printf(_("You are now connected to database \"%s\" as user \"%s\" on host \"%s\" at port \"%s\".\n"),
3314 						   PQdb(pset.db), PQuser(pset.db), host, PQport(pset.db));
3315 			}
3316 		}
3317 		else
3318 			printf(_("You are now connected to database \"%s\" as user \"%s\".\n"),
3319 				   PQdb(pset.db), PQuser(pset.db));
3320 	}
3321 
3322 	if (o_conn)
3323 		PQfinish(o_conn);
3324 	return true;
3325 }
3326 
3327 
3328 void
connection_warnings(bool in_startup)3329 connection_warnings(bool in_startup)
3330 {
3331 	if (!pset.quiet && !pset.notty)
3332 	{
3333 		int			client_ver = PG_VERSION_NUM;
3334 		char		cverbuf[32];
3335 		char		sverbuf[32];
3336 
3337 		if (pset.sversion != client_ver)
3338 		{
3339 			const char *server_version;
3340 
3341 			/* Try to get full text form, might include "devel" etc */
3342 			server_version = PQparameterStatus(pset.db, "server_version");
3343 			/* Otherwise fall back on pset.sversion */
3344 			if (!server_version)
3345 			{
3346 				formatPGVersionNumber(pset.sversion, true,
3347 									  sverbuf, sizeof(sverbuf));
3348 				server_version = sverbuf;
3349 			}
3350 
3351 			printf(_("%s (%s, server %s)\n"),
3352 				   pset.progname, PG_VERSION, server_version);
3353 		}
3354 		/* For version match, only print psql banner on startup. */
3355 		else if (in_startup)
3356 			printf("%s (%s)\n", pset.progname, PG_VERSION);
3357 
3358 		if (pset.sversion / 100 > client_ver / 100)
3359 			printf(_("WARNING: %s major version %s, server major version %s.\n"
3360 					 "         Some psql features might not work.\n"),
3361 				   pset.progname,
3362 				   formatPGVersionNumber(client_ver, false,
3363 										 cverbuf, sizeof(cverbuf)),
3364 				   formatPGVersionNumber(pset.sversion, false,
3365 										 sverbuf, sizeof(sverbuf)));
3366 
3367 #ifdef WIN32
3368 		if (in_startup)
3369 			checkWin32Codepage();
3370 #endif
3371 		printSSLInfo();
3372 		printGSSInfo();
3373 	}
3374 }
3375 
3376 
3377 /*
3378  * printSSLInfo
3379  *
3380  * Prints information about the current SSL connection, if SSL is in use
3381  */
3382 static void
printSSLInfo(void)3383 printSSLInfo(void)
3384 {
3385 	const char *protocol;
3386 	const char *cipher;
3387 	const char *bits;
3388 	const char *compression;
3389 
3390 	if (!PQsslInUse(pset.db))
3391 		return;					/* no SSL */
3392 
3393 	protocol = PQsslAttribute(pset.db, "protocol");
3394 	cipher = PQsslAttribute(pset.db, "cipher");
3395 	bits = PQsslAttribute(pset.db, "key_bits");
3396 	compression = PQsslAttribute(pset.db, "compression");
3397 
3398 	printf(_("SSL connection (protocol: %s, cipher: %s, bits: %s, compression: %s)\n"),
3399 		   protocol ? protocol : _("unknown"),
3400 		   cipher ? cipher : _("unknown"),
3401 		   bits ? bits : _("unknown"),
3402 		   (compression && strcmp(compression, "off") != 0) ? _("on") : _("off"));
3403 }
3404 
3405 /*
3406  * printGSSInfo
3407  *
3408  * Prints information about the current GSSAPI connection, if GSSAPI encryption is in use
3409  */
3410 static void
printGSSInfo(void)3411 printGSSInfo(void)
3412 {
3413 	if (!PQgssEncInUse(pset.db))
3414 		return;					/* no GSSAPI encryption in use */
3415 
3416 	printf(_("GSSAPI-encrypted connection\n"));
3417 }
3418 
3419 
3420 /*
3421  * checkWin32Codepage
3422  *
3423  * Prints a warning when win32 console codepage differs from Windows codepage
3424  */
3425 #ifdef WIN32
3426 static void
checkWin32Codepage(void)3427 checkWin32Codepage(void)
3428 {
3429 	unsigned int wincp,
3430 				concp;
3431 
3432 	wincp = GetACP();
3433 	concp = GetConsoleCP();
3434 	if (wincp != concp)
3435 	{
3436 		printf(_("WARNING: Console code page (%u) differs from Windows code page (%u)\n"
3437 				 "         8-bit characters might not work correctly. See psql reference\n"
3438 				 "         page \"Notes for Windows users\" for details.\n"),
3439 			   concp, wincp);
3440 	}
3441 }
3442 #endif
3443 
3444 
3445 /*
3446  * SyncVariables
3447  *
3448  * Make psql's internal variables agree with connection state upon
3449  * establishing a new connection.
3450  */
3451 void
SyncVariables(void)3452 SyncVariables(void)
3453 {
3454 	char		vbuf[32];
3455 	const char *server_version;
3456 
3457 	/* get stuff from connection */
3458 	pset.encoding = PQclientEncoding(pset.db);
3459 	pset.popt.topt.encoding = pset.encoding;
3460 	pset.sversion = PQserverVersion(pset.db);
3461 
3462 	SetVariable(pset.vars, "DBNAME", PQdb(pset.db));
3463 	SetVariable(pset.vars, "USER", PQuser(pset.db));
3464 	SetVariable(pset.vars, "HOST", PQhost(pset.db));
3465 	SetVariable(pset.vars, "PORT", PQport(pset.db));
3466 	SetVariable(pset.vars, "ENCODING", pg_encoding_to_char(pset.encoding));
3467 
3468 	/* this bit should match connection_warnings(): */
3469 	/* Try to get full text form of version, might include "devel" etc */
3470 	server_version = PQparameterStatus(pset.db, "server_version");
3471 	/* Otherwise fall back on pset.sversion */
3472 	if (!server_version)
3473 	{
3474 		formatPGVersionNumber(pset.sversion, true, vbuf, sizeof(vbuf));
3475 		server_version = vbuf;
3476 	}
3477 	SetVariable(pset.vars, "SERVER_VERSION_NAME", server_version);
3478 
3479 	snprintf(vbuf, sizeof(vbuf), "%d", pset.sversion);
3480 	SetVariable(pset.vars, "SERVER_VERSION_NUM", vbuf);
3481 
3482 	/* send stuff to it, too */
3483 	PQsetErrorVerbosity(pset.db, pset.verbosity);
3484 	PQsetErrorContextVisibility(pset.db, pset.show_context);
3485 }
3486 
3487 /*
3488  * UnsyncVariables
3489  *
3490  * Clear variables that should be not be set when there is no connection.
3491  */
3492 void
UnsyncVariables(void)3493 UnsyncVariables(void)
3494 {
3495 	SetVariable(pset.vars, "DBNAME", NULL);
3496 	SetVariable(pset.vars, "USER", NULL);
3497 	SetVariable(pset.vars, "HOST", NULL);
3498 	SetVariable(pset.vars, "PORT", NULL);
3499 	SetVariable(pset.vars, "ENCODING", NULL);
3500 	SetVariable(pset.vars, "SERVER_VERSION_NAME", NULL);
3501 	SetVariable(pset.vars, "SERVER_VERSION_NUM", NULL);
3502 }
3503 
3504 
3505 /*
3506  * do_edit -- handler for \e
3507  *
3508  * If you do not specify a filename, the current query buffer will be copied
3509  * into a temporary one.
3510  */
3511 static bool
editFile(const char * fname,int lineno)3512 editFile(const char *fname, int lineno)
3513 {
3514 	const char *editorName;
3515 	const char *editor_lineno_arg = NULL;
3516 	char	   *sys;
3517 	int			result;
3518 
3519 	Assert(fname != NULL);
3520 
3521 	/* Find an editor to use */
3522 	editorName = getenv("PSQL_EDITOR");
3523 	if (!editorName)
3524 		editorName = getenv("EDITOR");
3525 	if (!editorName)
3526 		editorName = getenv("VISUAL");
3527 	if (!editorName)
3528 		editorName = DEFAULT_EDITOR;
3529 
3530 	/* Get line number argument, if we need it. */
3531 	if (lineno > 0)
3532 	{
3533 		editor_lineno_arg = getenv("PSQL_EDITOR_LINENUMBER_ARG");
3534 #ifdef DEFAULT_EDITOR_LINENUMBER_ARG
3535 		if (!editor_lineno_arg)
3536 			editor_lineno_arg = DEFAULT_EDITOR_LINENUMBER_ARG;
3537 #endif
3538 		if (!editor_lineno_arg)
3539 		{
3540 			pg_log_error("environment variable PSQL_EDITOR_LINENUMBER_ARG must be set to specify a line number");
3541 			return false;
3542 		}
3543 	}
3544 
3545 	/*
3546 	 * On Unix the EDITOR value should *not* be quoted, since it might include
3547 	 * switches, eg, EDITOR="pico -t"; it's up to the user to put quotes in it
3548 	 * if necessary.  But this policy is not very workable on Windows, due to
3549 	 * severe brain damage in their command shell plus the fact that standard
3550 	 * program paths include spaces.
3551 	 */
3552 #ifndef WIN32
3553 	if (lineno > 0)
3554 		sys = psprintf("exec %s %s%d '%s'",
3555 					   editorName, editor_lineno_arg, lineno, fname);
3556 	else
3557 		sys = psprintf("exec %s '%s'",
3558 					   editorName, fname);
3559 #else
3560 	if (lineno > 0)
3561 		sys = psprintf("\"%s\" %s%d \"%s\"",
3562 					   editorName, editor_lineno_arg, lineno, fname);
3563 	else
3564 		sys = psprintf("\"%s\" \"%s\"",
3565 					   editorName, fname);
3566 #endif
3567 	result = system(sys);
3568 	if (result == -1)
3569 		pg_log_error("could not start editor \"%s\"", editorName);
3570 	else if (result == 127)
3571 		pg_log_error("could not start /bin/sh");
3572 	free(sys);
3573 
3574 	return result == 0;
3575 }
3576 
3577 
3578 /* call this one */
3579 static bool
do_edit(const char * filename_arg,PQExpBuffer query_buf,int lineno,bool * edited)3580 do_edit(const char *filename_arg, PQExpBuffer query_buf,
3581 		int lineno, bool *edited)
3582 {
3583 	char		fnametmp[MAXPGPATH];
3584 	FILE	   *stream = NULL;
3585 	const char *fname;
3586 	bool		error = false;
3587 	int			fd;
3588 	struct stat before,
3589 				after;
3590 
3591 	if (filename_arg)
3592 		fname = filename_arg;
3593 	else
3594 	{
3595 		/* make a temp file to edit */
3596 #ifndef WIN32
3597 		const char *tmpdir = getenv("TMPDIR");
3598 
3599 		if (!tmpdir)
3600 			tmpdir = "/tmp";
3601 #else
3602 		char		tmpdir[MAXPGPATH];
3603 		int			ret;
3604 
3605 		ret = GetTempPath(MAXPGPATH, tmpdir);
3606 		if (ret == 0 || ret > MAXPGPATH)
3607 		{
3608 			pg_log_error("could not locate temporary directory: %s",
3609 						 !ret ? strerror(errno) : "");
3610 			return false;
3611 		}
3612 #endif
3613 
3614 		/*
3615 		 * No canonicalize_path() here. EDIT.EXE run from CMD.EXE prepends the
3616 		 * current directory to the supplied path unless we use only
3617 		 * backslashes, so we do that.
3618 		 */
3619 #ifndef WIN32
3620 		snprintf(fnametmp, sizeof(fnametmp), "%s%spsql.edit.%d.sql", tmpdir,
3621 				 "/", (int) getpid());
3622 #else
3623 		snprintf(fnametmp, sizeof(fnametmp), "%s%spsql.edit.%d.sql", tmpdir,
3624 				 "" /* trailing separator already present */ , (int) getpid());
3625 #endif
3626 
3627 		fname = (const char *) fnametmp;
3628 
3629 		fd = open(fname, O_WRONLY | O_CREAT | O_EXCL, 0600);
3630 		if (fd != -1)
3631 			stream = fdopen(fd, "w");
3632 
3633 		if (fd == -1 || !stream)
3634 		{
3635 			pg_log_error("could not open temporary file \"%s\": %m", fname);
3636 			error = true;
3637 		}
3638 		else
3639 		{
3640 			unsigned int ql = query_buf->len;
3641 
3642 			if (ql == 0 || query_buf->data[ql - 1] != '\n')
3643 			{
3644 				appendPQExpBufferChar(query_buf, '\n');
3645 				ql++;
3646 			}
3647 
3648 			if (fwrite(query_buf->data, 1, ql, stream) != ql)
3649 			{
3650 				pg_log_error("%s: %m", fname);
3651 
3652 				if (fclose(stream) != 0)
3653 					pg_log_error("%s: %m", fname);
3654 
3655 				if (remove(fname) != 0)
3656 					pg_log_error("%s: %m", fname);
3657 
3658 				error = true;
3659 			}
3660 			else if (fclose(stream) != 0)
3661 			{
3662 				pg_log_error("%s: %m", fname);
3663 				if (remove(fname) != 0)
3664 					pg_log_error("%s: %m", fname);
3665 				error = true;
3666 			}
3667 			else
3668 			{
3669 				struct utimbuf ut;
3670 
3671 				/*
3672 				 * Try to set the file modification time of the temporary file
3673 				 * a few seconds in the past.  Otherwise, the low granularity
3674 				 * (one second, or even worse on some filesystems) that we can
3675 				 * portably measure with stat(2) could lead us to not
3676 				 * recognize a modification, if the user typed very quickly.
3677 				 *
3678 				 * This is a rather unlikely race condition, so don't error
3679 				 * out if the utime(2) call fails --- that would make the cure
3680 				 * worse than the disease.
3681 				 */
3682 				ut.modtime = ut.actime = time(NULL) - 2;
3683 				(void) utime(fname, &ut);
3684 			}
3685 		}
3686 	}
3687 
3688 	if (!error && stat(fname, &before) != 0)
3689 	{
3690 		pg_log_error("%s: %m", fname);
3691 		error = true;
3692 	}
3693 
3694 	/* call editor */
3695 	if (!error)
3696 		error = !editFile(fname, lineno);
3697 
3698 	if (!error && stat(fname, &after) != 0)
3699 	{
3700 		pg_log_error("%s: %m", fname);
3701 		error = true;
3702 	}
3703 
3704 	/* file was edited if the size or modification time has changed */
3705 	if (!error &&
3706 		(before.st_size != after.st_size ||
3707 		 before.st_mtime != after.st_mtime))
3708 	{
3709 		stream = fopen(fname, PG_BINARY_R);
3710 		if (!stream)
3711 		{
3712 			pg_log_error("%s: %m", fname);
3713 			error = true;
3714 		}
3715 		else
3716 		{
3717 			/* read file back into query_buf */
3718 			char		line[1024];
3719 
3720 			resetPQExpBuffer(query_buf);
3721 			while (fgets(line, sizeof(line), stream) != NULL)
3722 				appendPQExpBufferStr(query_buf, line);
3723 
3724 			if (ferror(stream))
3725 			{
3726 				pg_log_error("%s: %m", fname);
3727 				error = true;
3728 			}
3729 			else if (edited)
3730 			{
3731 				*edited = true;
3732 			}
3733 
3734 			fclose(stream);
3735 		}
3736 	}
3737 
3738 	/* remove temp file */
3739 	if (!filename_arg)
3740 	{
3741 		if (remove(fname) == -1)
3742 		{
3743 			pg_log_error("%s: %m", fname);
3744 			error = true;
3745 		}
3746 	}
3747 
3748 	return !error;
3749 }
3750 
3751 
3752 
3753 /*
3754  * process_file
3755  *
3756  * Reads commands from filename and passes them to the main processing loop.
3757  * Handler for \i and \ir, but can be used for other things as well.  Returns
3758  * MainLoop() error code.
3759  *
3760  * If use_relative_path is true and filename is not an absolute path, then open
3761  * the file from where the currently processed file (if any) is located.
3762  */
3763 int
process_file(char * filename,bool use_relative_path)3764 process_file(char *filename, bool use_relative_path)
3765 {
3766 	FILE	   *fd;
3767 	int			result;
3768 	char	   *oldfilename;
3769 	char		relpath[MAXPGPATH];
3770 
3771 	if (!filename)
3772 	{
3773 		fd = stdin;
3774 		filename = NULL;
3775 	}
3776 	else if (strcmp(filename, "-") != 0)
3777 	{
3778 		canonicalize_path(filename);
3779 
3780 		/*
3781 		 * If we were asked to resolve the pathname relative to the location
3782 		 * of the currently executing script, and there is one, and this is a
3783 		 * relative pathname, then prepend all but the last pathname component
3784 		 * of the current script to this pathname.
3785 		 */
3786 		if (use_relative_path && pset.inputfile &&
3787 			!is_absolute_path(filename) && !has_drive_prefix(filename))
3788 		{
3789 			strlcpy(relpath, pset.inputfile, sizeof(relpath));
3790 			get_parent_directory(relpath);
3791 			join_path_components(relpath, relpath, filename);
3792 			canonicalize_path(relpath);
3793 
3794 			filename = relpath;
3795 		}
3796 
3797 		fd = fopen(filename, PG_BINARY_R);
3798 
3799 		if (!fd)
3800 		{
3801 			pg_log_error("%s: %m", filename);
3802 			return EXIT_FAILURE;
3803 		}
3804 	}
3805 	else
3806 	{
3807 		fd = stdin;
3808 		filename = "<stdin>";	/* for future error messages */
3809 	}
3810 
3811 	oldfilename = pset.inputfile;
3812 	pset.inputfile = filename;
3813 
3814 	pg_logging_config(pset.inputfile ? 0 : PG_LOG_FLAG_TERSE);
3815 
3816 	result = MainLoop(fd);
3817 
3818 	if (fd != stdin)
3819 		fclose(fd);
3820 
3821 	pset.inputfile = oldfilename;
3822 
3823 	pg_logging_config(pset.inputfile ? 0 : PG_LOG_FLAG_TERSE);
3824 
3825 	return result;
3826 }
3827 
3828 
3829 
3830 static const char *
_align2string(enum printFormat in)3831 _align2string(enum printFormat in)
3832 {
3833 	switch (in)
3834 	{
3835 		case PRINT_NOTHING:
3836 			return "nothing";
3837 			break;
3838 		case PRINT_ALIGNED:
3839 			return "aligned";
3840 			break;
3841 		case PRINT_ASCIIDOC:
3842 			return "asciidoc";
3843 			break;
3844 		case PRINT_CSV:
3845 			return "csv";
3846 			break;
3847 		case PRINT_HTML:
3848 			return "html";
3849 			break;
3850 		case PRINT_LATEX:
3851 			return "latex";
3852 			break;
3853 		case PRINT_LATEX_LONGTABLE:
3854 			return "latex-longtable";
3855 			break;
3856 		case PRINT_TROFF_MS:
3857 			return "troff-ms";
3858 			break;
3859 		case PRINT_UNALIGNED:
3860 			return "unaligned";
3861 			break;
3862 		case PRINT_WRAPPED:
3863 			return "wrapped";
3864 			break;
3865 	}
3866 	return "unknown";
3867 }
3868 
3869 /*
3870  * Parse entered Unicode linestyle.  If ok, update *linestyle and return
3871  * true, else return false.
3872  */
3873 static bool
set_unicode_line_style(const char * value,size_t vallen,unicode_linestyle * linestyle)3874 set_unicode_line_style(const char *value, size_t vallen,
3875 					   unicode_linestyle *linestyle)
3876 {
3877 	if (pg_strncasecmp("single", value, vallen) == 0)
3878 		*linestyle = UNICODE_LINESTYLE_SINGLE;
3879 	else if (pg_strncasecmp("double", value, vallen) == 0)
3880 		*linestyle = UNICODE_LINESTYLE_DOUBLE;
3881 	else
3882 		return false;
3883 	return true;
3884 }
3885 
3886 static const char *
_unicode_linestyle2string(int linestyle)3887 _unicode_linestyle2string(int linestyle)
3888 {
3889 	switch (linestyle)
3890 	{
3891 		case UNICODE_LINESTYLE_SINGLE:
3892 			return "single";
3893 			break;
3894 		case UNICODE_LINESTYLE_DOUBLE:
3895 			return "double";
3896 			break;
3897 	}
3898 	return "unknown";
3899 }
3900 
3901 /*
3902  * do_pset
3903  *
3904  */
3905 bool
do_pset(const char * param,const char * value,printQueryOpt * popt,bool quiet)3906 do_pset(const char *param, const char *value, printQueryOpt *popt, bool quiet)
3907 {
3908 	size_t		vallen = 0;
3909 
3910 	Assert(param != NULL);
3911 
3912 	if (value)
3913 		vallen = strlen(value);
3914 
3915 	/* set format */
3916 	if (strcmp(param, "format") == 0)
3917 	{
3918 		static const struct fmt
3919 		{
3920 			const char *name;
3921 			enum printFormat number;
3922 		}			formats[] =
3923 		{
3924 			/* remember to update error message below when adding more */
3925 			{"aligned", PRINT_ALIGNED},
3926 			{"asciidoc", PRINT_ASCIIDOC},
3927 			{"csv", PRINT_CSV},
3928 			{"html", PRINT_HTML},
3929 			{"latex", PRINT_LATEX},
3930 			{"troff-ms", PRINT_TROFF_MS},
3931 			{"unaligned", PRINT_UNALIGNED},
3932 			{"wrapped", PRINT_WRAPPED}
3933 		};
3934 
3935 		if (!value)
3936 			;
3937 		else
3938 		{
3939 			int			match_pos = -1;
3940 
3941 			for (int i = 0; i < lengthof(formats); i++)
3942 			{
3943 				if (pg_strncasecmp(formats[i].name, value, vallen) == 0)
3944 				{
3945 					if (match_pos < 0)
3946 						match_pos = i;
3947 					else
3948 					{
3949 						pg_log_error("\\pset: ambiguous abbreviation \"%s\" matches both \"%s\" and \"%s\"",
3950 									 value,
3951 									 formats[match_pos].name, formats[i].name);
3952 						return false;
3953 					}
3954 				}
3955 			}
3956 			if (match_pos >= 0)
3957 				popt->topt.format = formats[match_pos].number;
3958 			else if (pg_strncasecmp("latex-longtable", value, vallen) == 0)
3959 			{
3960 				/*
3961 				 * We must treat latex-longtable specially because latex is a
3962 				 * prefix of it; if both were in the table above, we'd think
3963 				 * "latex" is ambiguous.
3964 				 */
3965 				popt->topt.format = PRINT_LATEX_LONGTABLE;
3966 			}
3967 			else
3968 			{
3969 				pg_log_error("\\pset: allowed formats are aligned, asciidoc, csv, html, latex, latex-longtable, troff-ms, unaligned, wrapped");
3970 				return false;
3971 			}
3972 		}
3973 	}
3974 
3975 	/* set table line style */
3976 	else if (strcmp(param, "linestyle") == 0)
3977 	{
3978 		if (!value)
3979 			;
3980 		else if (pg_strncasecmp("ascii", value, vallen) == 0)
3981 			popt->topt.line_style = &pg_asciiformat;
3982 		else if (pg_strncasecmp("old-ascii", value, vallen) == 0)
3983 			popt->topt.line_style = &pg_asciiformat_old;
3984 		else if (pg_strncasecmp("unicode", value, vallen) == 0)
3985 			popt->topt.line_style = &pg_utf8format;
3986 		else
3987 		{
3988 			pg_log_error("\\pset: allowed line styles are ascii, old-ascii, unicode");
3989 			return false;
3990 		}
3991 	}
3992 
3993 	/* set unicode border line style */
3994 	else if (strcmp(param, "unicode_border_linestyle") == 0)
3995 	{
3996 		if (!value)
3997 			;
3998 		else if (set_unicode_line_style(value, vallen,
3999 										&popt->topt.unicode_border_linestyle))
4000 			refresh_utf8format(&(popt->topt));
4001 		else
4002 		{
4003 			pg_log_error("\\pset: allowed Unicode border line styles are single, double");
4004 			return false;
4005 		}
4006 	}
4007 
4008 	/* set unicode column line style */
4009 	else if (strcmp(param, "unicode_column_linestyle") == 0)
4010 	{
4011 		if (!value)
4012 			;
4013 		else if (set_unicode_line_style(value, vallen,
4014 										&popt->topt.unicode_column_linestyle))
4015 			refresh_utf8format(&(popt->topt));
4016 		else
4017 		{
4018 			pg_log_error("\\pset: allowed Unicode column line styles are single, double");
4019 			return false;
4020 		}
4021 	}
4022 
4023 	/* set unicode header line style */
4024 	else if (strcmp(param, "unicode_header_linestyle") == 0)
4025 	{
4026 		if (!value)
4027 			;
4028 		else if (set_unicode_line_style(value, vallen,
4029 										&popt->topt.unicode_header_linestyle))
4030 			refresh_utf8format(&(popt->topt));
4031 		else
4032 		{
4033 			pg_log_error("\\pset: allowed Unicode header line styles are single, double");
4034 			return false;
4035 		}
4036 	}
4037 
4038 	/* set border style/width */
4039 	else if (strcmp(param, "border") == 0)
4040 	{
4041 		if (value)
4042 			popt->topt.border = atoi(value);
4043 	}
4044 
4045 	/* set expanded/vertical mode */
4046 	else if (strcmp(param, "x") == 0 ||
4047 			 strcmp(param, "expanded") == 0 ||
4048 			 strcmp(param, "vertical") == 0)
4049 	{
4050 		if (value && pg_strcasecmp(value, "auto") == 0)
4051 			popt->topt.expanded = 2;
4052 		else if (value)
4053 		{
4054 			bool		on_off;
4055 
4056 			if (ParseVariableBool(value, NULL, &on_off))
4057 				popt->topt.expanded = on_off ? 1 : 0;
4058 			else
4059 			{
4060 				PsqlVarEnumError(param, value, "on, off, auto");
4061 				return false;
4062 			}
4063 		}
4064 		else
4065 			popt->topt.expanded = !popt->topt.expanded;
4066 	}
4067 
4068 	/* field separator for CSV format */
4069 	else if (strcmp(param, "csv_fieldsep") == 0)
4070 	{
4071 		if (value)
4072 		{
4073 			/* CSV separator has to be a one-byte character */
4074 			if (strlen(value) != 1)
4075 			{
4076 				pg_log_error("\\pset: csv_fieldsep must be a single one-byte character");
4077 				return false;
4078 			}
4079 			if (value[0] == '"' || value[0] == '\n' || value[0] == '\r')
4080 			{
4081 				pg_log_error("\\pset: csv_fieldsep cannot be a double quote, a newline, or a carriage return");
4082 				return false;
4083 			}
4084 			popt->topt.csvFieldSep[0] = value[0];
4085 		}
4086 	}
4087 
4088 	/* locale-aware numeric output */
4089 	else if (strcmp(param, "numericlocale") == 0)
4090 	{
4091 		if (value)
4092 			return ParseVariableBool(value, param, &popt->topt.numericLocale);
4093 		else
4094 			popt->topt.numericLocale = !popt->topt.numericLocale;
4095 	}
4096 
4097 	/* null display */
4098 	else if (strcmp(param, "null") == 0)
4099 	{
4100 		if (value)
4101 		{
4102 			free(popt->nullPrint);
4103 			popt->nullPrint = pg_strdup(value);
4104 		}
4105 	}
4106 
4107 	/* field separator for unaligned text */
4108 	else if (strcmp(param, "fieldsep") == 0)
4109 	{
4110 		if (value)
4111 		{
4112 			free(popt->topt.fieldSep.separator);
4113 			popt->topt.fieldSep.separator = pg_strdup(value);
4114 			popt->topt.fieldSep.separator_zero = false;
4115 		}
4116 	}
4117 
4118 	else if (strcmp(param, "fieldsep_zero") == 0)
4119 	{
4120 		free(popt->topt.fieldSep.separator);
4121 		popt->topt.fieldSep.separator = NULL;
4122 		popt->topt.fieldSep.separator_zero = true;
4123 	}
4124 
4125 	/* record separator for unaligned text */
4126 	else if (strcmp(param, "recordsep") == 0)
4127 	{
4128 		if (value)
4129 		{
4130 			free(popt->topt.recordSep.separator);
4131 			popt->topt.recordSep.separator = pg_strdup(value);
4132 			popt->topt.recordSep.separator_zero = false;
4133 		}
4134 	}
4135 
4136 	else if (strcmp(param, "recordsep_zero") == 0)
4137 	{
4138 		free(popt->topt.recordSep.separator);
4139 		popt->topt.recordSep.separator = NULL;
4140 		popt->topt.recordSep.separator_zero = true;
4141 	}
4142 
4143 	/* toggle between full and tuples-only format */
4144 	else if (strcmp(param, "t") == 0 || strcmp(param, "tuples_only") == 0)
4145 	{
4146 		if (value)
4147 			return ParseVariableBool(value, param, &popt->topt.tuples_only);
4148 		else
4149 			popt->topt.tuples_only = !popt->topt.tuples_only;
4150 	}
4151 
4152 	/* set title override */
4153 	else if (strcmp(param, "C") == 0 || strcmp(param, "title") == 0)
4154 	{
4155 		free(popt->title);
4156 		if (!value)
4157 			popt->title = NULL;
4158 		else
4159 			popt->title = pg_strdup(value);
4160 	}
4161 
4162 	/* set HTML table tag options */
4163 	else if (strcmp(param, "T") == 0 || strcmp(param, "tableattr") == 0)
4164 	{
4165 		free(popt->topt.tableAttr);
4166 		if (!value)
4167 			popt->topt.tableAttr = NULL;
4168 		else
4169 			popt->topt.tableAttr = pg_strdup(value);
4170 	}
4171 
4172 	/* toggle use of pager */
4173 	else if (strcmp(param, "pager") == 0)
4174 	{
4175 		if (value && pg_strcasecmp(value, "always") == 0)
4176 			popt->topt.pager = 2;
4177 		else if (value)
4178 		{
4179 			bool		on_off;
4180 
4181 			if (!ParseVariableBool(value, NULL, &on_off))
4182 			{
4183 				PsqlVarEnumError(param, value, "on, off, always");
4184 				return false;
4185 			}
4186 			popt->topt.pager = on_off ? 1 : 0;
4187 		}
4188 		else if (popt->topt.pager == 1)
4189 			popt->topt.pager = 0;
4190 		else
4191 			popt->topt.pager = 1;
4192 	}
4193 
4194 	/* set minimum lines for pager use */
4195 	else if (strcmp(param, "pager_min_lines") == 0)
4196 	{
4197 		if (value)
4198 			popt->topt.pager_min_lines = atoi(value);
4199 	}
4200 
4201 	/* disable "(x rows)" footer */
4202 	else if (strcmp(param, "footer") == 0)
4203 	{
4204 		if (value)
4205 			return ParseVariableBool(value, param, &popt->topt.default_footer);
4206 		else
4207 			popt->topt.default_footer = !popt->topt.default_footer;
4208 	}
4209 
4210 	/* set border style/width */
4211 	else if (strcmp(param, "columns") == 0)
4212 	{
4213 		if (value)
4214 			popt->topt.columns = atoi(value);
4215 	}
4216 	else
4217 	{
4218 		pg_log_error("\\pset: unknown option: %s", param);
4219 		return false;
4220 	}
4221 
4222 	if (!quiet)
4223 		printPsetInfo(param, &pset.popt);
4224 
4225 	return true;
4226 }
4227 
4228 
4229 static bool
printPsetInfo(const char * param,struct printQueryOpt * popt)4230 printPsetInfo(const char *param, struct printQueryOpt *popt)
4231 {
4232 	Assert(param != NULL);
4233 
4234 	/* show border style/width */
4235 	if (strcmp(param, "border") == 0)
4236 		printf(_("Border style is %d.\n"), popt->topt.border);
4237 
4238 	/* show the target width for the wrapped format */
4239 	else if (strcmp(param, "columns") == 0)
4240 	{
4241 		if (!popt->topt.columns)
4242 			printf(_("Target width is unset.\n"));
4243 		else
4244 			printf(_("Target width is %d.\n"), popt->topt.columns);
4245 	}
4246 
4247 	/* show expanded/vertical mode */
4248 	else if (strcmp(param, "x") == 0 || strcmp(param, "expanded") == 0 || strcmp(param, "vertical") == 0)
4249 	{
4250 		if (popt->topt.expanded == 1)
4251 			printf(_("Expanded display is on.\n"));
4252 		else if (popt->topt.expanded == 2)
4253 			printf(_("Expanded display is used automatically.\n"));
4254 		else
4255 			printf(_("Expanded display is off.\n"));
4256 	}
4257 
4258 	/* show field separator for CSV format */
4259 	else if (strcmp(param, "csv_fieldsep") == 0)
4260 	{
4261 		printf(_("Field separator for CSV is \"%s\".\n"),
4262 			   popt->topt.csvFieldSep);
4263 	}
4264 
4265 	/* show field separator for unaligned text */
4266 	else if (strcmp(param, "fieldsep") == 0)
4267 	{
4268 		if (popt->topt.fieldSep.separator_zero)
4269 			printf(_("Field separator is zero byte.\n"));
4270 		else
4271 			printf(_("Field separator is \"%s\".\n"),
4272 				   popt->topt.fieldSep.separator);
4273 	}
4274 
4275 	else if (strcmp(param, "fieldsep_zero") == 0)
4276 	{
4277 		printf(_("Field separator is zero byte.\n"));
4278 	}
4279 
4280 	/* show disable "(x rows)" footer */
4281 	else if (strcmp(param, "footer") == 0)
4282 	{
4283 		if (popt->topt.default_footer)
4284 			printf(_("Default footer is on.\n"));
4285 		else
4286 			printf(_("Default footer is off.\n"));
4287 	}
4288 
4289 	/* show format */
4290 	else if (strcmp(param, "format") == 0)
4291 	{
4292 		printf(_("Output format is %s.\n"), _align2string(popt->topt.format));
4293 	}
4294 
4295 	/* show table line style */
4296 	else if (strcmp(param, "linestyle") == 0)
4297 	{
4298 		printf(_("Line style is %s.\n"),
4299 			   get_line_style(&popt->topt)->name);
4300 	}
4301 
4302 	/* show null display */
4303 	else if (strcmp(param, "null") == 0)
4304 	{
4305 		printf(_("Null display is \"%s\".\n"),
4306 			   popt->nullPrint ? popt->nullPrint : "");
4307 	}
4308 
4309 	/* show locale-aware numeric output */
4310 	else if (strcmp(param, "numericlocale") == 0)
4311 	{
4312 		if (popt->topt.numericLocale)
4313 			printf(_("Locale-adjusted numeric output is on.\n"));
4314 		else
4315 			printf(_("Locale-adjusted numeric output is off.\n"));
4316 	}
4317 
4318 	/* show toggle use of pager */
4319 	else if (strcmp(param, "pager") == 0)
4320 	{
4321 		if (popt->topt.pager == 1)
4322 			printf(_("Pager is used for long output.\n"));
4323 		else if (popt->topt.pager == 2)
4324 			printf(_("Pager is always used.\n"));
4325 		else
4326 			printf(_("Pager usage is off.\n"));
4327 	}
4328 
4329 	/* show minimum lines for pager use */
4330 	else if (strcmp(param, "pager_min_lines") == 0)
4331 	{
4332 		printf(ngettext("Pager won't be used for less than %d line.\n",
4333 						"Pager won't be used for less than %d lines.\n",
4334 						popt->topt.pager_min_lines),
4335 			   popt->topt.pager_min_lines);
4336 	}
4337 
4338 	/* show record separator for unaligned text */
4339 	else if (strcmp(param, "recordsep") == 0)
4340 	{
4341 		if (popt->topt.recordSep.separator_zero)
4342 			printf(_("Record separator is zero byte.\n"));
4343 		else if (strcmp(popt->topt.recordSep.separator, "\n") == 0)
4344 			printf(_("Record separator is <newline>.\n"));
4345 		else
4346 			printf(_("Record separator is \"%s\".\n"),
4347 				   popt->topt.recordSep.separator);
4348 	}
4349 
4350 	else if (strcmp(param, "recordsep_zero") == 0)
4351 	{
4352 		printf(_("Record separator is zero byte.\n"));
4353 	}
4354 
4355 	/* show HTML table tag options */
4356 	else if (strcmp(param, "T") == 0 || strcmp(param, "tableattr") == 0)
4357 	{
4358 		if (popt->topt.tableAttr)
4359 			printf(_("Table attributes are \"%s\".\n"),
4360 				   popt->topt.tableAttr);
4361 		else
4362 			printf(_("Table attributes unset.\n"));
4363 	}
4364 
4365 	/* show title override */
4366 	else if (strcmp(param, "C") == 0 || strcmp(param, "title") == 0)
4367 	{
4368 		if (popt->title)
4369 			printf(_("Title is \"%s\".\n"), popt->title);
4370 		else
4371 			printf(_("Title is unset.\n"));
4372 	}
4373 
4374 	/* show toggle between full and tuples-only format */
4375 	else if (strcmp(param, "t") == 0 || strcmp(param, "tuples_only") == 0)
4376 	{
4377 		if (popt->topt.tuples_only)
4378 			printf(_("Tuples only is on.\n"));
4379 		else
4380 			printf(_("Tuples only is off.\n"));
4381 	}
4382 
4383 	/* Unicode style formatting */
4384 	else if (strcmp(param, "unicode_border_linestyle") == 0)
4385 	{
4386 		printf(_("Unicode border line style is \"%s\".\n"),
4387 			   _unicode_linestyle2string(popt->topt.unicode_border_linestyle));
4388 	}
4389 
4390 	else if (strcmp(param, "unicode_column_linestyle") == 0)
4391 	{
4392 		printf(_("Unicode column line style is \"%s\".\n"),
4393 			   _unicode_linestyle2string(popt->topt.unicode_column_linestyle));
4394 	}
4395 
4396 	else if (strcmp(param, "unicode_header_linestyle") == 0)
4397 	{
4398 		printf(_("Unicode header line style is \"%s\".\n"),
4399 			   _unicode_linestyle2string(popt->topt.unicode_header_linestyle));
4400 	}
4401 
4402 	else
4403 	{
4404 		pg_log_error("\\pset: unknown option: %s", param);
4405 		return false;
4406 	}
4407 
4408 	return true;
4409 }
4410 
4411 
4412 static const char *
pset_bool_string(bool val)4413 pset_bool_string(bool val)
4414 {
4415 	return val ? "on" : "off";
4416 }
4417 
4418 
4419 static char *
pset_quoted_string(const char * str)4420 pset_quoted_string(const char *str)
4421 {
4422 	char	   *ret = pg_malloc(strlen(str) * 2 + 3);
4423 	char	   *r = ret;
4424 
4425 	*r++ = '\'';
4426 
4427 	for (; *str; str++)
4428 	{
4429 		if (*str == '\n')
4430 		{
4431 			*r++ = '\\';
4432 			*r++ = 'n';
4433 		}
4434 		else if (*str == '\'')
4435 		{
4436 			*r++ = '\\';
4437 			*r++ = '\'';
4438 		}
4439 		else
4440 			*r++ = *str;
4441 	}
4442 
4443 	*r++ = '\'';
4444 	*r = '\0';
4445 
4446 	return ret;
4447 }
4448 
4449 
4450 /*
4451  * Return a malloc'ed string for the \pset value.
4452  *
4453  * Note that for some string parameters, print.c distinguishes between unset
4454  * and empty string, but for others it doesn't.  This function should produce
4455  * output that produces the correct setting when fed back into \pset.
4456  */
4457 static char *
pset_value_string(const char * param,struct printQueryOpt * popt)4458 pset_value_string(const char *param, struct printQueryOpt *popt)
4459 {
4460 	Assert(param != NULL);
4461 
4462 	if (strcmp(param, "border") == 0)
4463 		return psprintf("%d", popt->topt.border);
4464 	else if (strcmp(param, "columns") == 0)
4465 		return psprintf("%d", popt->topt.columns);
4466 	else if (strcmp(param, "csv_fieldsep") == 0)
4467 		return pset_quoted_string(popt->topt.csvFieldSep);
4468 	else if (strcmp(param, "expanded") == 0)
4469 		return pstrdup(popt->topt.expanded == 2
4470 					   ? "auto"
4471 					   : pset_bool_string(popt->topt.expanded));
4472 	else if (strcmp(param, "fieldsep") == 0)
4473 		return pset_quoted_string(popt->topt.fieldSep.separator
4474 								  ? popt->topt.fieldSep.separator
4475 								  : "");
4476 	else if (strcmp(param, "fieldsep_zero") == 0)
4477 		return pstrdup(pset_bool_string(popt->topt.fieldSep.separator_zero));
4478 	else if (strcmp(param, "footer") == 0)
4479 		return pstrdup(pset_bool_string(popt->topt.default_footer));
4480 	else if (strcmp(param, "format") == 0)
4481 		return psprintf("%s", _align2string(popt->topt.format));
4482 	else if (strcmp(param, "linestyle") == 0)
4483 		return psprintf("%s", get_line_style(&popt->topt)->name);
4484 	else if (strcmp(param, "null") == 0)
4485 		return pset_quoted_string(popt->nullPrint
4486 								  ? popt->nullPrint
4487 								  : "");
4488 	else if (strcmp(param, "numericlocale") == 0)
4489 		return pstrdup(pset_bool_string(popt->topt.numericLocale));
4490 	else if (strcmp(param, "pager") == 0)
4491 		return psprintf("%d", popt->topt.pager);
4492 	else if (strcmp(param, "pager_min_lines") == 0)
4493 		return psprintf("%d", popt->topt.pager_min_lines);
4494 	else if (strcmp(param, "recordsep") == 0)
4495 		return pset_quoted_string(popt->topt.recordSep.separator
4496 								  ? popt->topt.recordSep.separator
4497 								  : "");
4498 	else if (strcmp(param, "recordsep_zero") == 0)
4499 		return pstrdup(pset_bool_string(popt->topt.recordSep.separator_zero));
4500 	else if (strcmp(param, "tableattr") == 0)
4501 		return popt->topt.tableAttr ? pset_quoted_string(popt->topt.tableAttr) : pstrdup("");
4502 	else if (strcmp(param, "title") == 0)
4503 		return popt->title ? pset_quoted_string(popt->title) : pstrdup("");
4504 	else if (strcmp(param, "tuples_only") == 0)
4505 		return pstrdup(pset_bool_string(popt->topt.tuples_only));
4506 	else if (strcmp(param, "unicode_border_linestyle") == 0)
4507 		return pstrdup(_unicode_linestyle2string(popt->topt.unicode_border_linestyle));
4508 	else if (strcmp(param, "unicode_column_linestyle") == 0)
4509 		return pstrdup(_unicode_linestyle2string(popt->topt.unicode_column_linestyle));
4510 	else if (strcmp(param, "unicode_header_linestyle") == 0)
4511 		return pstrdup(_unicode_linestyle2string(popt->topt.unicode_header_linestyle));
4512 	else
4513 		return pstrdup("ERROR");
4514 }
4515 
4516 
4517 
4518 #ifndef WIN32
4519 #define DEFAULT_SHELL "/bin/sh"
4520 #else
4521 /*
4522  *	CMD.EXE is in different places in different Win32 releases so we
4523  *	have to rely on the path to find it.
4524  */
4525 #define DEFAULT_SHELL "cmd.exe"
4526 #endif
4527 
4528 static bool
do_shell(const char * command)4529 do_shell(const char *command)
4530 {
4531 	int			result;
4532 
4533 	if (!command)
4534 	{
4535 		char	   *sys;
4536 		const char *shellName;
4537 
4538 		shellName = getenv("SHELL");
4539 #ifdef WIN32
4540 		if (shellName == NULL)
4541 			shellName = getenv("COMSPEC");
4542 #endif
4543 		if (shellName == NULL)
4544 			shellName = DEFAULT_SHELL;
4545 
4546 		/* See EDITOR handling comment for an explanation */
4547 #ifndef WIN32
4548 		sys = psprintf("exec %s", shellName);
4549 #else
4550 		sys = psprintf("\"%s\"", shellName);
4551 #endif
4552 		result = system(sys);
4553 		free(sys);
4554 	}
4555 	else
4556 		result = system(command);
4557 
4558 	if (result == 127 || result == -1)
4559 	{
4560 		pg_log_error("\\!: failed");
4561 		return false;
4562 	}
4563 	return true;
4564 }
4565 
4566 /*
4567  * do_watch -- handler for \watch
4568  *
4569  * We break this out of exec_command to avoid having to plaster "volatile"
4570  * onto a bunch of exec_command's variables to silence stupider compilers.
4571  */
4572 static bool
do_watch(PQExpBuffer query_buf,double sleep)4573 do_watch(PQExpBuffer query_buf, double sleep)
4574 {
4575 	long		sleep_ms = (long) (sleep * 1000);
4576 	printQueryOpt myopt = pset.popt;
4577 	const char *strftime_fmt;
4578 	const char *user_title;
4579 	char	   *title;
4580 	int			title_len;
4581 	int			res = 0;
4582 
4583 	if (!query_buf || query_buf->len <= 0)
4584 	{
4585 		pg_log_error("\\watch cannot be used with an empty query");
4586 		return false;
4587 	}
4588 
4589 	/*
4590 	 * Choose format for timestamps.  We might eventually make this a \pset
4591 	 * option.  In the meantime, using a variable for the format suppresses
4592 	 * overly-anal-retentive gcc warnings about %c being Y2K sensitive.
4593 	 */
4594 	strftime_fmt = "%c";
4595 
4596 	/*
4597 	 * Set up rendering options, in particular, disable the pager, because
4598 	 * nobody wants to be prompted while watching the output of 'watch'.
4599 	 */
4600 	myopt.topt.pager = 0;
4601 
4602 	/*
4603 	 * If there's a title in the user configuration, make sure we have room
4604 	 * for it in the title buffer.  Allow 128 bytes for the timestamp plus 128
4605 	 * bytes for the rest.
4606 	 */
4607 	user_title = myopt.title;
4608 	title_len = (user_title ? strlen(user_title) : 0) + 256;
4609 	title = pg_malloc(title_len);
4610 
4611 	for (;;)
4612 	{
4613 		time_t		timer;
4614 		char		timebuf[128];
4615 		long		i;
4616 
4617 		/*
4618 		 * Prepare title for output.  Note that we intentionally include a
4619 		 * newline at the end of the title; this is somewhat historical but it
4620 		 * makes for reasonably nicely formatted output in simple cases.
4621 		 */
4622 		timer = time(NULL);
4623 		strftime(timebuf, sizeof(timebuf), strftime_fmt, localtime(&timer));
4624 
4625 		if (user_title)
4626 			snprintf(title, title_len, _("%s\t%s (every %gs)\n"),
4627 					 user_title, timebuf, sleep);
4628 		else
4629 			snprintf(title, title_len, _("%s (every %gs)\n"),
4630 					 timebuf, sleep);
4631 		myopt.title = title;
4632 
4633 		/* Run the query and print out the results */
4634 		res = PSQLexecWatch(query_buf->data, &myopt);
4635 
4636 		/*
4637 		 * PSQLexecWatch handles the case where we can no longer repeat the
4638 		 * query, and returns 0 or -1.
4639 		 */
4640 		if (res <= 0)
4641 			break;
4642 
4643 		/*
4644 		 * Set up cancellation of 'watch' via SIGINT.  We redo this each time
4645 		 * through the loop since it's conceivable something inside
4646 		 * PSQLexecWatch could change sigint_interrupt_jmp.
4647 		 */
4648 		if (sigsetjmp(sigint_interrupt_jmp, 1) != 0)
4649 			break;
4650 
4651 		/*
4652 		 * Enable 'watch' cancellations and wait a while before running the
4653 		 * query again.  Break the sleep into short intervals (at most 1s)
4654 		 * since pg_usleep isn't interruptible on some platforms.
4655 		 */
4656 		sigint_interrupt_enabled = true;
4657 		i = sleep_ms;
4658 		while (i > 0)
4659 		{
4660 			long		s = Min(i, 1000L);
4661 
4662 			pg_usleep(s * 1000L);
4663 			if (cancel_pressed)
4664 				break;
4665 			i -= s;
4666 		}
4667 		sigint_interrupt_enabled = false;
4668 	}
4669 
4670 	pg_free(title);
4671 	return (res >= 0);
4672 }
4673 
4674 /*
4675  * a little code borrowed from PSQLexec() to manage ECHO_HIDDEN output.
4676  * returns true unless we have ECHO_HIDDEN_NOEXEC.
4677  */
4678 static bool
echo_hidden_command(const char * query)4679 echo_hidden_command(const char *query)
4680 {
4681 	if (pset.echo_hidden != PSQL_ECHO_HIDDEN_OFF)
4682 	{
4683 		printf(_("********* QUERY **********\n"
4684 				 "%s\n"
4685 				 "**************************\n\n"), query);
4686 		fflush(stdout);
4687 		if (pset.logfile)
4688 		{
4689 			fprintf(pset.logfile,
4690 					_("********* QUERY **********\n"
4691 					  "%s\n"
4692 					  "**************************\n\n"), query);
4693 			fflush(pset.logfile);
4694 		}
4695 
4696 		if (pset.echo_hidden == PSQL_ECHO_HIDDEN_NOEXEC)
4697 			return false;
4698 	}
4699 	return true;
4700 }
4701 
4702 /*
4703  * Look up the object identified by obj_type and desc.  If successful,
4704  * store its OID in *obj_oid and return true, else return false.
4705  *
4706  * Note that we'll fail if the object doesn't exist OR if there are multiple
4707  * matching candidates OR if there's something syntactically wrong with the
4708  * object description; unfortunately it can be hard to tell the difference.
4709  */
4710 static bool
lookup_object_oid(EditableObjectType obj_type,const char * desc,Oid * obj_oid)4711 lookup_object_oid(EditableObjectType obj_type, const char *desc,
4712 				  Oid *obj_oid)
4713 {
4714 	bool		result = true;
4715 	PQExpBuffer query = createPQExpBuffer();
4716 	PGresult   *res;
4717 
4718 	switch (obj_type)
4719 	{
4720 		case EditableFunction:
4721 
4722 			/*
4723 			 * We have a function description, e.g. "x" or "x(int)".  Issue a
4724 			 * query to retrieve the function's OID using a cast to regproc or
4725 			 * regprocedure (as appropriate).
4726 			 */
4727 			appendPQExpBufferStr(query, "SELECT ");
4728 			appendStringLiteralConn(query, desc, pset.db);
4729 			appendPQExpBuffer(query, "::pg_catalog.%s::pg_catalog.oid",
4730 							  strchr(desc, '(') ? "regprocedure" : "regproc");
4731 			break;
4732 
4733 		case EditableView:
4734 
4735 			/*
4736 			 * Convert view name (possibly schema-qualified) to OID.  Note:
4737 			 * this code doesn't check if the relation is actually a view.
4738 			 * We'll detect that in get_create_object_cmd().
4739 			 */
4740 			appendPQExpBufferStr(query, "SELECT ");
4741 			appendStringLiteralConn(query, desc, pset.db);
4742 			appendPQExpBuffer(query, "::pg_catalog.regclass::pg_catalog.oid");
4743 			break;
4744 	}
4745 
4746 	if (!echo_hidden_command(query->data))
4747 	{
4748 		destroyPQExpBuffer(query);
4749 		return false;
4750 	}
4751 	res = PQexec(pset.db, query->data);
4752 	if (PQresultStatus(res) == PGRES_TUPLES_OK && PQntuples(res) == 1)
4753 		*obj_oid = atooid(PQgetvalue(res, 0, 0));
4754 	else
4755 	{
4756 		minimal_error_message(res);
4757 		result = false;
4758 	}
4759 
4760 	PQclear(res);
4761 	destroyPQExpBuffer(query);
4762 
4763 	return result;
4764 }
4765 
4766 /*
4767  * Construct a "CREATE OR REPLACE ..." command that describes the specified
4768  * database object.  If successful, the result is stored in buf.
4769  */
4770 static bool
get_create_object_cmd(EditableObjectType obj_type,Oid oid,PQExpBuffer buf)4771 get_create_object_cmd(EditableObjectType obj_type, Oid oid,
4772 					  PQExpBuffer buf)
4773 {
4774 	bool		result = true;
4775 	PQExpBuffer query = createPQExpBuffer();
4776 	PGresult   *res;
4777 
4778 	switch (obj_type)
4779 	{
4780 		case EditableFunction:
4781 			printfPQExpBuffer(query,
4782 							  "SELECT pg_catalog.pg_get_functiondef(%u)",
4783 							  oid);
4784 			break;
4785 
4786 		case EditableView:
4787 
4788 			/*
4789 			 * pg_get_viewdef() just prints the query, so we must prepend
4790 			 * CREATE for ourselves.  We must fully qualify the view name to
4791 			 * ensure the right view gets replaced.  Also, check relation kind
4792 			 * to be sure it's a view.
4793 			 *
4794 			 * Starting with 9.2, views may have reloptions (security_barrier)
4795 			 * and from 9.4 onwards they may also have WITH [LOCAL|CASCADED]
4796 			 * CHECK OPTION.  These are not part of the view definition
4797 			 * returned by pg_get_viewdef() and so need to be retrieved
4798 			 * separately.  Materialized views (introduced in 9.3) may have
4799 			 * arbitrary storage parameter reloptions.
4800 			 */
4801 			if (pset.sversion >= 90400)
4802 			{
4803 				printfPQExpBuffer(query,
4804 								  "SELECT nspname, relname, relkind, "
4805 								  "pg_catalog.pg_get_viewdef(c.oid, true), "
4806 								  "pg_catalog.array_remove(pg_catalog.array_remove(c.reloptions,'check_option=local'),'check_option=cascaded') AS reloptions, "
4807 								  "CASE WHEN 'check_option=local' = ANY (c.reloptions) THEN 'LOCAL'::text "
4808 								  "WHEN 'check_option=cascaded' = ANY (c.reloptions) THEN 'CASCADED'::text ELSE NULL END AS checkoption "
4809 								  "FROM pg_catalog.pg_class c "
4810 								  "LEFT JOIN pg_catalog.pg_namespace n "
4811 								  "ON c.relnamespace = n.oid WHERE c.oid = %u",
4812 								  oid);
4813 			}
4814 			else if (pset.sversion >= 90200)
4815 			{
4816 				printfPQExpBuffer(query,
4817 								  "SELECT nspname, relname, relkind, "
4818 								  "pg_catalog.pg_get_viewdef(c.oid, true), "
4819 								  "c.reloptions AS reloptions, "
4820 								  "NULL AS checkoption "
4821 								  "FROM pg_catalog.pg_class c "
4822 								  "LEFT JOIN pg_catalog.pg_namespace n "
4823 								  "ON c.relnamespace = n.oid WHERE c.oid = %u",
4824 								  oid);
4825 			}
4826 			else
4827 			{
4828 				printfPQExpBuffer(query,
4829 								  "SELECT nspname, relname, relkind, "
4830 								  "pg_catalog.pg_get_viewdef(c.oid, true), "
4831 								  "NULL AS reloptions, "
4832 								  "NULL AS checkoption "
4833 								  "FROM pg_catalog.pg_class c "
4834 								  "LEFT JOIN pg_catalog.pg_namespace n "
4835 								  "ON c.relnamespace = n.oid WHERE c.oid = %u",
4836 								  oid);
4837 			}
4838 			break;
4839 	}
4840 
4841 	if (!echo_hidden_command(query->data))
4842 	{
4843 		destroyPQExpBuffer(query);
4844 		return false;
4845 	}
4846 	res = PQexec(pset.db, query->data);
4847 	if (PQresultStatus(res) == PGRES_TUPLES_OK && PQntuples(res) == 1)
4848 	{
4849 		resetPQExpBuffer(buf);
4850 		switch (obj_type)
4851 		{
4852 			case EditableFunction:
4853 				appendPQExpBufferStr(buf, PQgetvalue(res, 0, 0));
4854 				break;
4855 
4856 			case EditableView:
4857 				{
4858 					char	   *nspname = PQgetvalue(res, 0, 0);
4859 					char	   *relname = PQgetvalue(res, 0, 1);
4860 					char	   *relkind = PQgetvalue(res, 0, 2);
4861 					char	   *viewdef = PQgetvalue(res, 0, 3);
4862 					char	   *reloptions = PQgetvalue(res, 0, 4);
4863 					char	   *checkoption = PQgetvalue(res, 0, 5);
4864 
4865 					/*
4866 					 * If the backend ever supports CREATE OR REPLACE
4867 					 * MATERIALIZED VIEW, allow that here; but as of today it
4868 					 * does not, so editing a matview definition in this way
4869 					 * is impossible.
4870 					 */
4871 					switch (relkind[0])
4872 					{
4873 #ifdef NOT_USED
4874 						case RELKIND_MATVIEW:
4875 							appendPQExpBufferStr(buf, "CREATE OR REPLACE MATERIALIZED VIEW ");
4876 							break;
4877 #endif
4878 						case RELKIND_VIEW:
4879 							appendPQExpBufferStr(buf, "CREATE OR REPLACE VIEW ");
4880 							break;
4881 						default:
4882 							pg_log_error("\"%s.%s\" is not a view",
4883 										 nspname, relname);
4884 							result = false;
4885 							break;
4886 					}
4887 					appendPQExpBuffer(buf, "%s.", fmtId(nspname));
4888 					appendPQExpBufferStr(buf, fmtId(relname));
4889 
4890 					/* reloptions, if not an empty array "{}" */
4891 					if (reloptions != NULL && strlen(reloptions) > 2)
4892 					{
4893 						appendPQExpBufferStr(buf, "\n WITH (");
4894 						if (!appendReloptionsArray(buf, reloptions, "",
4895 												   pset.encoding,
4896 												   standard_strings()))
4897 						{
4898 							pg_log_error("could not parse reloptions array");
4899 							result = false;
4900 						}
4901 						appendPQExpBufferChar(buf, ')');
4902 					}
4903 
4904 					/* View definition from pg_get_viewdef (a SELECT query) */
4905 					appendPQExpBuffer(buf, " AS\n%s", viewdef);
4906 
4907 					/* Get rid of the semicolon that pg_get_viewdef appends */
4908 					if (buf->len > 0 && buf->data[buf->len - 1] == ';')
4909 						buf->data[--(buf->len)] = '\0';
4910 
4911 					/* WITH [LOCAL|CASCADED] CHECK OPTION */
4912 					if (checkoption && checkoption[0] != '\0')
4913 						appendPQExpBuffer(buf, "\n WITH %s CHECK OPTION",
4914 										  checkoption);
4915 				}
4916 				break;
4917 		}
4918 		/* Make sure result ends with a newline */
4919 		if (buf->len > 0 && buf->data[buf->len - 1] != '\n')
4920 			appendPQExpBufferChar(buf, '\n');
4921 	}
4922 	else
4923 	{
4924 		minimal_error_message(res);
4925 		result = false;
4926 	}
4927 
4928 	PQclear(res);
4929 	destroyPQExpBuffer(query);
4930 
4931 	return result;
4932 }
4933 
4934 /*
4935  * If the given argument of \ef or \ev ends with a line number, delete the line
4936  * number from the argument string and return it as an integer.  (We need
4937  * this kluge because we're too lazy to parse \ef's function or \ev's view
4938  * argument carefully --- we just slop it up in OT_WHOLE_LINE mode.)
4939  *
4940  * Returns -1 if no line number is present, 0 on error, or a positive value
4941  * on success.
4942  */
4943 static int
strip_lineno_from_objdesc(char * obj)4944 strip_lineno_from_objdesc(char *obj)
4945 {
4946 	char	   *c;
4947 	int			lineno;
4948 
4949 	if (!obj || obj[0] == '\0')
4950 		return -1;
4951 
4952 	c = obj + strlen(obj) - 1;
4953 
4954 	/*
4955 	 * This business of parsing backwards is dangerous as can be in a
4956 	 * multibyte environment: there is no reason to believe that we are
4957 	 * looking at the first byte of a character, nor are we necessarily
4958 	 * working in a "safe" encoding.  Fortunately the bitpatterns we are
4959 	 * looking for are unlikely to occur as non-first bytes, but beware of
4960 	 * trying to expand the set of cases that can be recognized.  We must
4961 	 * guard the <ctype.h> macros by using isascii() first, too.
4962 	 */
4963 
4964 	/* skip trailing whitespace */
4965 	while (c > obj && isascii((unsigned char) *c) && isspace((unsigned char) *c))
4966 		c--;
4967 
4968 	/* must have a digit as last non-space char */
4969 	if (c == obj || !isascii((unsigned char) *c) || !isdigit((unsigned char) *c))
4970 		return -1;
4971 
4972 	/* find start of digit string */
4973 	while (c > obj && isascii((unsigned char) *c) && isdigit((unsigned char) *c))
4974 		c--;
4975 
4976 	/* digits must be separated from object name by space or closing paren */
4977 	/* notice also that we are not allowing an empty object name ... */
4978 	if (c == obj || !isascii((unsigned char) *c) ||
4979 		!(isspace((unsigned char) *c) || *c == ')'))
4980 		return -1;
4981 
4982 	/* parse digit string */
4983 	c++;
4984 	lineno = atoi(c);
4985 	if (lineno < 1)
4986 	{
4987 		pg_log_error("invalid line number: %s", c);
4988 		return 0;
4989 	}
4990 
4991 	/* strip digit string from object name */
4992 	*c = '\0';
4993 
4994 	return lineno;
4995 }
4996 
4997 /*
4998  * Count number of lines in the buffer.
4999  * This is used to test if pager is needed or not.
5000  */
5001 static int
count_lines_in_buf(PQExpBuffer buf)5002 count_lines_in_buf(PQExpBuffer buf)
5003 {
5004 	int			lineno = 0;
5005 	const char *lines = buf->data;
5006 
5007 	while (*lines != '\0')
5008 	{
5009 		lineno++;
5010 		/* find start of next line */
5011 		lines = strchr(lines, '\n');
5012 		if (!lines)
5013 			break;
5014 		lines++;
5015 	}
5016 
5017 	return lineno;
5018 }
5019 
5020 /*
5021  * Write text at *lines to output with line numbers.
5022  *
5023  * If header_keyword isn't NULL, then line 1 should be the first line beginning
5024  * with header_keyword; lines before that are unnumbered.
5025  *
5026  * Caution: this scribbles on *lines.
5027  */
5028 static void
print_with_linenumbers(FILE * output,char * lines,const char * header_keyword)5029 print_with_linenumbers(FILE *output, char *lines,
5030 					   const char *header_keyword)
5031 {
5032 	bool		in_header = (header_keyword != NULL);
5033 	size_t		header_sz = in_header ? strlen(header_keyword) : 0;
5034 	int			lineno = 0;
5035 
5036 	while (*lines != '\0')
5037 	{
5038 		char	   *eol;
5039 
5040 		if (in_header && strncmp(lines, header_keyword, header_sz) == 0)
5041 			in_header = false;
5042 
5043 		/* increment lineno only for body's lines */
5044 		if (!in_header)
5045 			lineno++;
5046 
5047 		/* find and mark end of current line */
5048 		eol = strchr(lines, '\n');
5049 		if (eol != NULL)
5050 			*eol = '\0';
5051 
5052 		/* show current line as appropriate */
5053 		if (in_header)
5054 			fprintf(output, "        %s\n", lines);
5055 		else
5056 			fprintf(output, "%-7d %s\n", lineno, lines);
5057 
5058 		/* advance to next line, if any */
5059 		if (eol == NULL)
5060 			break;
5061 		lines = ++eol;
5062 	}
5063 }
5064 
5065 /*
5066  * Report just the primary error; this is to avoid cluttering the output
5067  * with, for instance, a redisplay of the internally generated query
5068  */
5069 static void
minimal_error_message(PGresult * res)5070 minimal_error_message(PGresult *res)
5071 {
5072 	PQExpBuffer msg;
5073 	const char *fld;
5074 
5075 	msg = createPQExpBuffer();
5076 
5077 	fld = PQresultErrorField(res, PG_DIAG_SEVERITY);
5078 	if (fld)
5079 		printfPQExpBuffer(msg, "%s:  ", fld);
5080 	else
5081 		printfPQExpBuffer(msg, "ERROR:  ");
5082 	fld = PQresultErrorField(res, PG_DIAG_MESSAGE_PRIMARY);
5083 	if (fld)
5084 		appendPQExpBufferStr(msg, fld);
5085 	else
5086 		appendPQExpBufferStr(msg, "(not available)");
5087 	appendPQExpBufferChar(msg, '\n');
5088 
5089 	pg_log_error("%s", msg->data);
5090 
5091 	destroyPQExpBuffer(msg);
5092 }
5093