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