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