1 /*
2  * psql - the PostgreSQL interactive terminal
3  *
4  * Copyright (c) 2000-2016, PostgreSQL Global Development Group
5  *
6  * src/bin/psql/command.c
7  */
8 #include "postgres_fe.h"
9 #include "command.h"
10 
11 #ifdef __BORLANDC__				/* needed for BCC */
12 #undef mkdir
13 #endif
14 
15 #include <ctype.h>
16 #include <time.h>
17 #ifdef HAVE_PWD_H
18 #include <pwd.h>
19 #endif
20 #include <utime.h>
21 #ifndef WIN32
22 #include <sys/types.h>			/* for umask() */
23 #include <sys/stat.h>			/* for stat() */
24 #include <fcntl.h>				/* open() flags */
25 #include <unistd.h>				/* for geteuid(), getpid(), stat() */
26 #else
27 #include <win32.h>
28 #include <io.h>
29 #include <fcntl.h>
30 #include <direct.h>
31 #include <sys/types.h>			/* for umask() */
32 #include <sys/stat.h>			/* for stat() */
33 #endif
34 
35 #include "portability/instr_time.h"
36 
37 #include "libpq-fe.h"
38 #include "pqexpbuffer.h"
39 #include "fe_utils/string_utils.h"
40 
41 #include "common.h"
42 #include "copy.h"
43 #include "crosstabview.h"
44 #include "describe.h"
45 #include "help.h"
46 #include "input.h"
47 #include "large_obj.h"
48 #include "mainloop.h"
49 #include "fe_utils/print.h"
50 #include "psqlscanslash.h"
51 #include "settings.h"
52 #include "variables.h"
53 
54 /*
55  * Editable database object types.
56  */
57 typedef enum EditableObjectType
58 {
59 	EditableFunction,
60 	EditableView
61 } EditableObjectType;
62 
63 /* functions for use in this file */
64 static backslashResult exec_command(const char *cmd,
65 			 PsqlScanState scan_state,
66 			 PQExpBuffer query_buf);
67 static bool do_edit(const char *filename_arg, PQExpBuffer query_buf,
68 		int lineno, bool *edited);
69 static bool do_connect(enum trivalue reuse_previous_specification,
70 		   char *dbname, char *user, char *host, char *port);
71 static bool do_shell(const char *command);
72 static bool do_watch(PQExpBuffer query_buf, double sleep);
73 static bool lookup_object_oid(EditableObjectType obj_type, const char *desc,
74 				  Oid *obj_oid);
75 static bool get_create_object_cmd(EditableObjectType obj_type, Oid oid,
76 					  PQExpBuffer buf);
77 static int	strip_lineno_from_objdesc(char *obj);
78 static int	count_lines_in_buf(PQExpBuffer buf);
79 static void print_with_linenumbers(FILE *output, char *lines,
80 					   const char *header_keyword);
81 static void minimal_error_message(PGresult *res);
82 
83 static void printSSLInfo(void);
84 static bool printPsetInfo(const char *param, struct printQueryOpt *popt);
85 static char *pset_value_string(const char *param, struct printQueryOpt *popt);
86 
87 #ifdef WIN32
88 static void checkWin32Codepage(void);
89 #endif
90 
91 
92 
93 /*----------
94  * HandleSlashCmds:
95  *
96  * Handles all the different commands that start with '\'.
97  * Ordinarily called by MainLoop().
98  *
99  * scan_state is a lexer working state that is set to continue scanning
100  * just after the '\'.  The lexer is advanced past the command and all
101  * arguments on return.
102  *
103  * 'query_buf' contains the query-so-far, which may be modified by
104  * execution of the backslash command (for example, \r clears it).
105  * query_buf can be NULL if there is no query so far.
106  *
107  * Returns a status code indicating what action is desired, see command.h.
108  *----------
109  */
110 
111 backslashResult
HandleSlashCmds(PsqlScanState scan_state,PQExpBuffer query_buf)112 HandleSlashCmds(PsqlScanState scan_state,
113 				PQExpBuffer query_buf)
114 {
115 	backslashResult status = PSQL_CMD_SKIP_LINE;
116 	char	   *cmd;
117 	char	   *arg;
118 
119 	Assert(scan_state != NULL);
120 
121 	/* Parse off the command name */
122 	cmd = psql_scan_slash_command(scan_state);
123 
124 	/* And try to execute it */
125 	status = exec_command(cmd, scan_state, query_buf);
126 
127 	if (status == PSQL_CMD_UNKNOWN)
128 	{
129 		if (pset.cur_cmd_interactive)
130 			psql_error("Invalid command \\%s. Try \\? for help.\n", cmd);
131 		else
132 			psql_error("invalid command \\%s\n", cmd);
133 		status = PSQL_CMD_ERROR;
134 	}
135 
136 	if (status != PSQL_CMD_ERROR)
137 	{
138 		/* eat any remaining arguments after a valid command */
139 		/* note we suppress evaluation of backticks here */
140 		while ((arg = psql_scan_slash_option(scan_state,
141 											 OT_NO_EVAL, NULL, false)))
142 		{
143 			psql_error("\\%s: extra argument \"%s\" ignored\n", cmd, arg);
144 			free(arg);
145 		}
146 	}
147 	else
148 	{
149 		/* silently throw away rest of line after an erroneous command */
150 		while ((arg = psql_scan_slash_option(scan_state,
151 											 OT_WHOLE_LINE, NULL, false)))
152 			free(arg);
153 	}
154 
155 	/* if there is a trailing \\, swallow it */
156 	psql_scan_slash_command_end(scan_state);
157 
158 	free(cmd);
159 
160 	/* some commands write to queryFout, so make sure output is sent */
161 	fflush(pset.queryFout);
162 
163 	return status;
164 }
165 
166 /*
167  * Read and interpret an argument to the \connect slash command.
168  */
169 static char *
read_connect_arg(PsqlScanState scan_state)170 read_connect_arg(PsqlScanState scan_state)
171 {
172 	char	   *result;
173 	char		quote;
174 
175 	/*
176 	 * Ideally we should treat the arguments as SQL identifiers.  But for
177 	 * backwards compatibility with 7.2 and older pg_dump files, we have to
178 	 * take unquoted arguments verbatim (don't downcase them). For now,
179 	 * double-quoted arguments may be stripped of double quotes (as if SQL
180 	 * identifiers).  By 7.4 or so, pg_dump files can be expected to
181 	 * double-quote all mixed-case \connect arguments, and then we can get rid
182 	 * of OT_SQLIDHACK.
183 	 */
184 	result = psql_scan_slash_option(scan_state, OT_SQLIDHACK, &quote, true);
185 
186 	if (!result)
187 		return NULL;
188 
189 	if (quote)
190 		return result;
191 
192 	if (*result == '\0' || strcmp(result, "-") == 0)
193 		return NULL;
194 
195 	return result;
196 }
197 
198 
199 /*
200  * Subroutine to actually try to execute a backslash command.
201  */
202 static backslashResult
exec_command(const char * cmd,PsqlScanState scan_state,PQExpBuffer query_buf)203 exec_command(const char *cmd,
204 			 PsqlScanState scan_state,
205 			 PQExpBuffer query_buf)
206 {
207 	bool		success = true; /* indicate here if the command ran ok or
208 								 * failed */
209 	backslashResult status = PSQL_CMD_SKIP_LINE;
210 
211 	/*
212 	 * \a -- toggle field alignment This makes little sense but we keep it
213 	 * around.
214 	 */
215 	if (strcmp(cmd, "a") == 0)
216 	{
217 		if (pset.popt.topt.format != PRINT_ALIGNED)
218 			success = do_pset("format", "aligned", &pset.popt, pset.quiet);
219 		else
220 			success = do_pset("format", "unaligned", &pset.popt, pset.quiet);
221 	}
222 
223 	/* \C -- override table title (formerly change HTML caption) */
224 	else if (strcmp(cmd, "C") == 0)
225 	{
226 		char	   *opt = psql_scan_slash_option(scan_state,
227 												 OT_NORMAL, NULL, true);
228 
229 		success = do_pset("title", opt, &pset.popt, pset.quiet);
230 		free(opt);
231 	}
232 
233 	/*
234 	 * \c or \connect -- connect to database using the specified parameters.
235 	 *
236 	 * \c [-reuse-previous=BOOL] dbname user host port
237 	 *
238 	 * Specifying a parameter as '-' is equivalent to omitting it.  Examples:
239 	 *
240 	 * \c - - hst		Connect to current database on current port of host
241 	 * "hst" as current user. \c - usr - prt   Connect to current database on
242 	 * "prt" port of current host as user "usr". \c dbs			  Connect to
243 	 * "dbs" database on current port of current host as current user.
244 	 */
245 	else if (strcmp(cmd, "c") == 0 || strcmp(cmd, "connect") == 0)
246 	{
247 		static const char prefix[] = "-reuse-previous=";
248 		char	   *opt1,
249 				   *opt2,
250 				   *opt3,
251 				   *opt4;
252 		enum trivalue reuse_previous;
253 
254 		opt1 = read_connect_arg(scan_state);
255 		if (opt1 != NULL && strncmp(opt1, prefix, sizeof(prefix) - 1) == 0)
256 		{
257 			reuse_previous =
258 				ParseVariableBool(opt1 + sizeof(prefix) - 1, prefix) ?
259 				TRI_YES : TRI_NO;
260 
261 			free(opt1);
262 			opt1 = read_connect_arg(scan_state);
263 		}
264 		else
265 			reuse_previous = TRI_DEFAULT;
266 
267 		opt2 = read_connect_arg(scan_state);
268 		opt3 = read_connect_arg(scan_state);
269 		opt4 = read_connect_arg(scan_state);
270 
271 		success = do_connect(reuse_previous, opt1, opt2, opt3, opt4);
272 
273 		free(opt1);
274 		free(opt2);
275 		free(opt3);
276 		free(opt4);
277 	}
278 
279 	/* \cd */
280 	else if (strcmp(cmd, "cd") == 0)
281 	{
282 		char	   *opt = psql_scan_slash_option(scan_state,
283 												 OT_NORMAL, NULL, true);
284 		char	   *dir;
285 
286 		if (opt)
287 			dir = opt;
288 		else
289 		{
290 #ifndef WIN32
291 			struct passwd *pw;
292 			uid_t		user_id = geteuid();
293 
294 			errno = 0;			/* clear errno before call */
295 			pw = getpwuid(user_id);
296 			if (!pw)
297 			{
298 				psql_error("could not get home directory for user ID %ld: %s\n",
299 						   (long) user_id,
300 						 errno ? strerror(errno) : _("user does not exist"));
301 				exit(EXIT_FAILURE);
302 			}
303 			dir = pw->pw_dir;
304 #else							/* WIN32 */
305 
306 			/*
307 			 * On Windows, 'cd' without arguments prints the current
308 			 * directory, so if someone wants to code this here instead...
309 			 */
310 			dir = "/";
311 #endif   /* WIN32 */
312 		}
313 
314 		if (chdir(dir) == -1)
315 		{
316 			psql_error("\\%s: could not change directory to \"%s\": %s\n",
317 					   cmd, dir, strerror(errno));
318 			success = false;
319 		}
320 
321 		if (opt)
322 			free(opt);
323 	}
324 
325 	/* \conninfo -- display information about the current connection */
326 	else if (strcmp(cmd, "conninfo") == 0)
327 	{
328 		char	   *db = PQdb(pset.db);
329 
330 		if (db == NULL)
331 			printf(_("You are currently not connected to a database.\n"));
332 		else
333 		{
334 			char	   *host;
335 			PQconninfoOption *connOptions;
336 			PQconninfoOption *option;
337 
338 			host = PQhost(pset.db);
339 			/* A usable "hostaddr" overrides the basic sense of host. */
340 			connOptions = PQconninfo(pset.db);
341 			if (connOptions == NULL)
342 			{
343 				psql_error("out of memory\n");
344 				exit(EXIT_FAILURE);
345 			}
346 			for (option = connOptions; option && option->keyword; option++)
347 				if (strcmp(option->keyword, "hostaddr") == 0)
348 				{
349 					if (option->val != NULL && option->val[0] != '\0')
350 						host = option->val;
351 					break;
352 				}
353 
354 			/* If the host is an absolute path, the connection is via socket */
355 			if (is_absolute_path(host))
356 				printf(_("You are connected to database \"%s\" as user \"%s\" via socket in \"%s\" at port \"%s\".\n"),
357 					   db, PQuser(pset.db), host, PQport(pset.db));
358 			else
359 				printf(_("You are connected to database \"%s\" as user \"%s\" on host \"%s\" at port \"%s\".\n"),
360 					   db, PQuser(pset.db), host, PQport(pset.db));
361 			printSSLInfo();
362 
363 			PQconninfoFree(connOptions);
364 		}
365 	}
366 
367 	/* \copy */
368 	else if (pg_strcasecmp(cmd, "copy") == 0)
369 	{
370 		char	   *opt = psql_scan_slash_option(scan_state,
371 												 OT_WHOLE_LINE, NULL, false);
372 
373 		success = do_copy(opt);
374 		free(opt);
375 	}
376 
377 	/* \copyright */
378 	else if (strcmp(cmd, "copyright") == 0)
379 		print_copyright();
380 
381 	/* \crosstabview -- execute a query and display results in crosstab */
382 	else if (strcmp(cmd, "crosstabview") == 0)
383 	{
384 		int			i;
385 
386 		for (i = 0; i < lengthof(pset.ctv_args); i++)
387 			pset.ctv_args[i] = psql_scan_slash_option(scan_state,
388 													  OT_NORMAL, NULL, true);
389 		pset.crosstab_flag = true;
390 		status = PSQL_CMD_SEND;
391 	}
392 
393 	/* \d* commands */
394 	else if (cmd[0] == 'd')
395 	{
396 		char	   *pattern;
397 		bool		show_verbose,
398 					show_system;
399 
400 		/* We don't do SQLID reduction on the pattern yet */
401 		pattern = psql_scan_slash_option(scan_state,
402 										 OT_NORMAL, NULL, true);
403 
404 		show_verbose = strchr(cmd, '+') ? true : false;
405 		show_system = strchr(cmd, 'S') ? true : false;
406 
407 		switch (cmd[1])
408 		{
409 			case '\0':
410 			case '+':
411 			case 'S':
412 				if (pattern)
413 					success = describeTableDetails(pattern, show_verbose, show_system);
414 				else
415 					/* standard listing of interesting things */
416 					success = listTables("tvmsE", NULL, show_verbose, show_system);
417 				break;
418 			case 'A':
419 				success = describeAccessMethods(pattern, show_verbose);
420 				break;
421 			case 'a':
422 				success = describeAggregates(pattern, show_verbose, show_system);
423 				break;
424 			case 'b':
425 				success = describeTablespaces(pattern, show_verbose);
426 				break;
427 			case 'c':
428 				success = listConversions(pattern, show_verbose, show_system);
429 				break;
430 			case 'C':
431 				success = listCasts(pattern, show_verbose);
432 				break;
433 			case 'd':
434 				if (strncmp(cmd, "ddp", 3) == 0)
435 					success = listDefaultACLs(pattern);
436 				else
437 					success = objectDescription(pattern, show_system);
438 				break;
439 			case 'D':
440 				success = listDomains(pattern, show_verbose, show_system);
441 				break;
442 			case 'f':			/* function subsystem */
443 				switch (cmd[2])
444 				{
445 					case '\0':
446 					case '+':
447 					case 'S':
448 					case 'a':
449 					case 'n':
450 					case 't':
451 					case 'w':
452 						success = describeFunctions(&cmd[2], pattern, show_verbose, show_system);
453 						break;
454 					default:
455 						status = PSQL_CMD_UNKNOWN;
456 						break;
457 				}
458 				break;
459 			case 'g':
460 				/* no longer distinct from \du */
461 				success = describeRoles(pattern, show_verbose, show_system);
462 				break;
463 			case 'l':
464 				success = do_lo_list();
465 				break;
466 			case 'L':
467 				success = listLanguages(pattern, show_verbose, show_system);
468 				break;
469 			case 'n':
470 				success = listSchemas(pattern, show_verbose, show_system);
471 				break;
472 			case 'o':
473 				success = describeOperators(pattern, show_verbose, show_system);
474 				break;
475 			case 'O':
476 				success = listCollations(pattern, show_verbose, show_system);
477 				break;
478 			case 'p':
479 				success = permissionsList(pattern);
480 				break;
481 			case 'T':
482 				success = describeTypes(pattern, show_verbose, show_system);
483 				break;
484 			case 't':
485 			case 'v':
486 			case 'm':
487 			case 'i':
488 			case 's':
489 			case 'E':
490 				success = listTables(&cmd[1], pattern, show_verbose, show_system);
491 				break;
492 			case 'r':
493 				if (cmd[2] == 'd' && cmd[3] == 's')
494 				{
495 					char	   *pattern2 = NULL;
496 
497 					if (pattern)
498 						pattern2 = psql_scan_slash_option(scan_state,
499 													  OT_NORMAL, NULL, true);
500 					success = listDbRoleSettings(pattern, pattern2);
501 				}
502 				else
503 					success = PSQL_CMD_UNKNOWN;
504 				break;
505 			case 'u':
506 				success = describeRoles(pattern, show_verbose, show_system);
507 				break;
508 			case 'F':			/* text search subsystem */
509 				switch (cmd[2])
510 				{
511 					case '\0':
512 					case '+':
513 						success = listTSConfigs(pattern, show_verbose);
514 						break;
515 					case 'p':
516 						success = listTSParsers(pattern, show_verbose);
517 						break;
518 					case 'd':
519 						success = listTSDictionaries(pattern, show_verbose);
520 						break;
521 					case 't':
522 						success = listTSTemplates(pattern, show_verbose);
523 						break;
524 					default:
525 						status = PSQL_CMD_UNKNOWN;
526 						break;
527 				}
528 				break;
529 			case 'e':			/* SQL/MED subsystem */
530 				switch (cmd[2])
531 				{
532 					case 's':
533 						success = listForeignServers(pattern, show_verbose);
534 						break;
535 					case 'u':
536 						success = listUserMappings(pattern, show_verbose);
537 						break;
538 					case 'w':
539 						success = listForeignDataWrappers(pattern, show_verbose);
540 						break;
541 					case 't':
542 						success = listForeignTables(pattern, show_verbose);
543 						break;
544 					default:
545 						status = PSQL_CMD_UNKNOWN;
546 						break;
547 				}
548 				break;
549 			case 'x':			/* Extensions */
550 				if (show_verbose)
551 					success = listExtensionContents(pattern);
552 				else
553 					success = listExtensions(pattern);
554 				break;
555 			case 'y':			/* Event Triggers */
556 				success = listEventTriggers(pattern, show_verbose);
557 				break;
558 			default:
559 				status = PSQL_CMD_UNKNOWN;
560 		}
561 
562 		if (pattern)
563 			free(pattern);
564 	}
565 
566 
567 	/*
568 	 * \e or \edit -- edit the current query buffer, or edit a file and make
569 	 * it the query buffer
570 	 */
571 	else if (strcmp(cmd, "e") == 0 || strcmp(cmd, "edit") == 0)
572 	{
573 		if (!query_buf)
574 		{
575 			psql_error("no query buffer\n");
576 			status = PSQL_CMD_ERROR;
577 		}
578 		else
579 		{
580 			char	   *fname;
581 			char	   *ln = NULL;
582 			int			lineno = -1;
583 
584 			fname = psql_scan_slash_option(scan_state,
585 										   OT_NORMAL, NULL, true);
586 			if (fname)
587 			{
588 				/* try to get separate lineno arg */
589 				ln = psql_scan_slash_option(scan_state,
590 											OT_NORMAL, NULL, true);
591 				if (ln == NULL)
592 				{
593 					/* only one arg; maybe it is lineno not fname */
594 					if (fname[0] &&
595 						strspn(fname, "0123456789") == strlen(fname))
596 					{
597 						/* all digits, so assume it is lineno */
598 						ln = fname;
599 						fname = NULL;
600 					}
601 				}
602 			}
603 			if (ln)
604 			{
605 				lineno = atoi(ln);
606 				if (lineno < 1)
607 				{
608 					psql_error("invalid line number: %s\n", ln);
609 					status = PSQL_CMD_ERROR;
610 				}
611 			}
612 			if (status != PSQL_CMD_ERROR)
613 			{
614 				expand_tilde(&fname);
615 				if (fname)
616 					canonicalize_path(fname);
617 				if (do_edit(fname, query_buf, lineno, NULL))
618 					status = PSQL_CMD_NEWEDIT;
619 				else
620 					status = PSQL_CMD_ERROR;
621 			}
622 			if (fname)
623 				free(fname);
624 			if (ln)
625 				free(ln);
626 		}
627 	}
628 
629 	/*
630 	 * \ef -- edit the named function, or present a blank CREATE FUNCTION
631 	 * template if no argument is given
632 	 */
633 	else if (strcmp(cmd, "ef") == 0)
634 	{
635 		int			lineno = -1;
636 
637 		if (pset.sversion < 80400)
638 		{
639 			char		sverbuf[32];
640 
641 			psql_error("The server (version %s) does not support editing function source.\n",
642 					   formatPGVersionNumber(pset.sversion, false,
643 											 sverbuf, sizeof(sverbuf)));
644 			status = PSQL_CMD_ERROR;
645 		}
646 		else if (!query_buf)
647 		{
648 			psql_error("no query buffer\n");
649 			status = PSQL_CMD_ERROR;
650 		}
651 		else
652 		{
653 			char	   *func;
654 			Oid			foid = InvalidOid;
655 
656 			func = psql_scan_slash_option(scan_state,
657 										  OT_WHOLE_LINE, NULL, true);
658 			lineno = strip_lineno_from_objdesc(func);
659 			if (lineno == 0)
660 			{
661 				/* error already reported */
662 				status = PSQL_CMD_ERROR;
663 			}
664 			else if (!func)
665 			{
666 				/* set up an empty command to fill in */
667 				printfPQExpBuffer(query_buf,
668 								  "CREATE FUNCTION ( )\n"
669 								  " RETURNS \n"
670 								  " LANGUAGE \n"
671 								  " -- common options:  IMMUTABLE  STABLE  STRICT  SECURITY DEFINER\n"
672 								  "AS $function$\n"
673 								  "\n$function$\n");
674 			}
675 			else if (!lookup_object_oid(EditableFunction, func, &foid))
676 			{
677 				/* error already reported */
678 				status = PSQL_CMD_ERROR;
679 			}
680 			else if (!get_create_object_cmd(EditableFunction, foid, query_buf))
681 			{
682 				/* error already reported */
683 				status = PSQL_CMD_ERROR;
684 			}
685 			else if (lineno > 0)
686 			{
687 				/*
688 				 * lineno "1" should correspond to the first line of the
689 				 * function body.  We expect that pg_get_functiondef() will
690 				 * emit that on a line beginning with "AS ", and that there
691 				 * can be no such line before the real start of the function
692 				 * body.  Increment lineno by the number of lines before that
693 				 * line, so that it becomes relative to the first line of the
694 				 * function definition.
695 				 */
696 				const char *lines = query_buf->data;
697 
698 				while (*lines != '\0')
699 				{
700 					if (strncmp(lines, "AS ", 3) == 0)
701 						break;
702 					lineno++;
703 					/* find start of next line */
704 					lines = strchr(lines, '\n');
705 					if (!lines)
706 						break;
707 					lines++;
708 				}
709 			}
710 
711 			if (func)
712 				free(func);
713 		}
714 
715 		if (status != PSQL_CMD_ERROR)
716 		{
717 			bool		edited = false;
718 
719 			if (!do_edit(NULL, query_buf, lineno, &edited))
720 				status = PSQL_CMD_ERROR;
721 			else if (!edited)
722 				puts(_("No changes"));
723 			else
724 				status = PSQL_CMD_NEWEDIT;
725 		}
726 	}
727 
728 	/*
729 	 * \ev -- edit the named view, or present a blank CREATE VIEW template if
730 	 * no argument is given
731 	 */
732 	else if (strcmp(cmd, "ev") == 0)
733 	{
734 		int			lineno = -1;
735 
736 		if (pset.sversion < 70400)
737 		{
738 			char		sverbuf[32];
739 
740 			psql_error("The server (version %s) does not support editing view definitions.\n",
741 					   formatPGVersionNumber(pset.sversion, false,
742 											 sverbuf, sizeof(sverbuf)));
743 			status = PSQL_CMD_ERROR;
744 		}
745 		else if (!query_buf)
746 		{
747 			psql_error("no query buffer\n");
748 			status = PSQL_CMD_ERROR;
749 		}
750 		else
751 		{
752 			char	   *view;
753 			Oid			view_oid = InvalidOid;
754 
755 			view = psql_scan_slash_option(scan_state,
756 										  OT_WHOLE_LINE, NULL, true);
757 			lineno = strip_lineno_from_objdesc(view);
758 			if (lineno == 0)
759 			{
760 				/* error already reported */
761 				status = PSQL_CMD_ERROR;
762 			}
763 			else if (!view)
764 			{
765 				/* set up an empty command to fill in */
766 				printfPQExpBuffer(query_buf,
767 								  "CREATE VIEW  AS\n"
768 								  " SELECT \n"
769 								  "  -- something...\n");
770 			}
771 			else if (!lookup_object_oid(EditableView, view, &view_oid))
772 			{
773 				/* error already reported */
774 				status = PSQL_CMD_ERROR;
775 			}
776 			else if (!get_create_object_cmd(EditableView, view_oid, query_buf))
777 			{
778 				/* error already reported */
779 				status = PSQL_CMD_ERROR;
780 			}
781 
782 			if (view)
783 				free(view);
784 		}
785 
786 		if (status != PSQL_CMD_ERROR)
787 		{
788 			bool		edited = false;
789 
790 			if (!do_edit(NULL, query_buf, lineno, &edited))
791 				status = PSQL_CMD_ERROR;
792 			else if (!edited)
793 				puts(_("No changes"));
794 			else
795 				status = PSQL_CMD_NEWEDIT;
796 		}
797 	}
798 
799 	/* \echo and \qecho */
800 	else if (strcmp(cmd, "echo") == 0 || strcmp(cmd, "qecho") == 0)
801 	{
802 		char	   *value;
803 		char		quoted;
804 		bool		no_newline = false;
805 		bool		first = true;
806 		FILE	   *fout;
807 
808 		if (strcmp(cmd, "qecho") == 0)
809 			fout = pset.queryFout;
810 		else
811 			fout = stdout;
812 
813 		while ((value = psql_scan_slash_option(scan_state,
814 											   OT_NORMAL, &quoted, false)))
815 		{
816 			if (!quoted && strcmp(value, "-n") == 0)
817 				no_newline = true;
818 			else
819 			{
820 				if (first)
821 					first = false;
822 				else
823 					fputc(' ', fout);
824 				fputs(value, fout);
825 			}
826 			free(value);
827 		}
828 		if (!no_newline)
829 			fputs("\n", fout);
830 	}
831 
832 	/* \encoding -- set/show client side encoding */
833 	else if (strcmp(cmd, "encoding") == 0)
834 	{
835 		char	   *encoding = psql_scan_slash_option(scan_state,
836 													  OT_NORMAL, NULL, false);
837 
838 		if (!encoding)
839 		{
840 			/* show encoding */
841 			puts(pg_encoding_to_char(pset.encoding));
842 		}
843 		else
844 		{
845 			/* set encoding */
846 			if (PQsetClientEncoding(pset.db, encoding) == -1)
847 				psql_error("%s: invalid encoding name or conversion procedure not found\n", encoding);
848 			else
849 			{
850 				/* save encoding info into psql internal data */
851 				pset.encoding = PQclientEncoding(pset.db);
852 				pset.popt.topt.encoding = pset.encoding;
853 				SetVariable(pset.vars, "ENCODING",
854 							pg_encoding_to_char(pset.encoding));
855 			}
856 			free(encoding);
857 		}
858 	}
859 
860 	/* \errverbose -- display verbose message from last failed query */
861 	else if (strcmp(cmd, "errverbose") == 0)
862 	{
863 		if (pset.last_error_result)
864 		{
865 			char	   *msg;
866 
867 			msg = PQresultVerboseErrorMessage(pset.last_error_result,
868 											  PQERRORS_VERBOSE,
869 											  PQSHOW_CONTEXT_ALWAYS);
870 			if (msg)
871 			{
872 				psql_error("%s", msg);
873 				PQfreemem(msg);
874 			}
875 			else
876 				puts(_("out of memory"));
877 		}
878 		else
879 			puts(_("There is no previous error."));
880 	}
881 
882 	/* \f -- change field separator */
883 	else if (strcmp(cmd, "f") == 0)
884 	{
885 		char	   *fname = psql_scan_slash_option(scan_state,
886 												   OT_NORMAL, NULL, false);
887 
888 		success = do_pset("fieldsep", fname, &pset.popt, pset.quiet);
889 		free(fname);
890 	}
891 
892 	/* \g [filename] -- send query, optionally with output to file/pipe */
893 	else if (strcmp(cmd, "g") == 0)
894 	{
895 		char	   *fname = psql_scan_slash_option(scan_state,
896 												   OT_FILEPIPE, NULL, false);
897 
898 		if (!fname)
899 			pset.gfname = NULL;
900 		else
901 		{
902 			expand_tilde(&fname);
903 			pset.gfname = pg_strdup(fname);
904 		}
905 		free(fname);
906 		status = PSQL_CMD_SEND;
907 	}
908 
909 	/* \gexec -- send query and execute each field of result */
910 	else if (strcmp(cmd, "gexec") == 0)
911 	{
912 		pset.gexec_flag = true;
913 		status = PSQL_CMD_SEND;
914 	}
915 
916 	/* \gset [prefix] -- send query and store result into variables */
917 	else if (strcmp(cmd, "gset") == 0)
918 	{
919 		char	   *prefix = psql_scan_slash_option(scan_state,
920 													OT_NORMAL, NULL, false);
921 
922 		if (prefix)
923 			pset.gset_prefix = prefix;
924 		else
925 		{
926 			/* we must set a non-NULL prefix to trigger storing */
927 			pset.gset_prefix = pg_strdup("");
928 		}
929 		/* gset_prefix is freed later */
930 		status = PSQL_CMD_SEND;
931 	}
932 
933 	/* help */
934 	else if (strcmp(cmd, "h") == 0 || strcmp(cmd, "help") == 0)
935 	{
936 		char	   *opt = psql_scan_slash_option(scan_state,
937 												 OT_WHOLE_LINE, NULL, false);
938 		size_t		len;
939 
940 		/* strip any trailing spaces and semicolons */
941 		if (opt)
942 		{
943 			len = strlen(opt);
944 			while (len > 0 &&
945 				   (isspace((unsigned char) opt[len - 1])
946 					|| opt[len - 1] == ';'))
947 				opt[--len] = '\0';
948 		}
949 
950 		helpSQL(opt, pset.popt.topt.pager);
951 		free(opt);
952 	}
953 
954 	/* HTML mode */
955 	else if (strcmp(cmd, "H") == 0 || strcmp(cmd, "html") == 0)
956 	{
957 		if (pset.popt.topt.format != PRINT_HTML)
958 			success = do_pset("format", "html", &pset.popt, pset.quiet);
959 		else
960 			success = do_pset("format", "aligned", &pset.popt, pset.quiet);
961 	}
962 
963 
964 	/* \i and \ir include files */
965 	else if (strcmp(cmd, "i") == 0 || strcmp(cmd, "include") == 0
966 		   || strcmp(cmd, "ir") == 0 || strcmp(cmd, "include_relative") == 0)
967 	{
968 		char	   *fname = psql_scan_slash_option(scan_state,
969 												   OT_NORMAL, NULL, true);
970 
971 		if (!fname)
972 		{
973 			psql_error("\\%s: missing required argument\n", cmd);
974 			success = false;
975 		}
976 		else
977 		{
978 			bool		include_relative;
979 
980 			include_relative = (strcmp(cmd, "ir") == 0
981 								|| strcmp(cmd, "include_relative") == 0);
982 			expand_tilde(&fname);
983 			success = (process_file(fname, include_relative) == EXIT_SUCCESS);
984 			free(fname);
985 		}
986 	}
987 
988 	/* \l is list databases */
989 	else if (strcmp(cmd, "l") == 0 || strcmp(cmd, "list") == 0 ||
990 			 strcmp(cmd, "l+") == 0 || strcmp(cmd, "list+") == 0)
991 	{
992 		char	   *pattern;
993 		bool		show_verbose;
994 
995 		pattern = psql_scan_slash_option(scan_state,
996 										 OT_NORMAL, NULL, true);
997 
998 		show_verbose = strchr(cmd, '+') ? true : false;
999 
1000 		success = listAllDbs(pattern, show_verbose);
1001 
1002 		if (pattern)
1003 			free(pattern);
1004 	}
1005 
1006 	/*
1007 	 * large object things
1008 	 */
1009 	else if (strncmp(cmd, "lo_", 3) == 0)
1010 	{
1011 		char	   *opt1,
1012 				   *opt2;
1013 
1014 		opt1 = psql_scan_slash_option(scan_state,
1015 									  OT_NORMAL, NULL, true);
1016 		opt2 = psql_scan_slash_option(scan_state,
1017 									  OT_NORMAL, NULL, true);
1018 
1019 		if (strcmp(cmd + 3, "export") == 0)
1020 		{
1021 			if (!opt2)
1022 			{
1023 				psql_error("\\%s: missing required argument\n", cmd);
1024 				success = false;
1025 			}
1026 			else
1027 			{
1028 				expand_tilde(&opt2);
1029 				success = do_lo_export(opt1, opt2);
1030 			}
1031 		}
1032 
1033 		else if (strcmp(cmd + 3, "import") == 0)
1034 		{
1035 			if (!opt1)
1036 			{
1037 				psql_error("\\%s: missing required argument\n", cmd);
1038 				success = false;
1039 			}
1040 			else
1041 			{
1042 				expand_tilde(&opt1);
1043 				success = do_lo_import(opt1, opt2);
1044 			}
1045 		}
1046 
1047 		else if (strcmp(cmd + 3, "list") == 0)
1048 			success = do_lo_list();
1049 
1050 		else if (strcmp(cmd + 3, "unlink") == 0)
1051 		{
1052 			if (!opt1)
1053 			{
1054 				psql_error("\\%s: missing required argument\n", cmd);
1055 				success = false;
1056 			}
1057 			else
1058 				success = do_lo_unlink(opt1);
1059 		}
1060 
1061 		else
1062 			status = PSQL_CMD_UNKNOWN;
1063 
1064 		free(opt1);
1065 		free(opt2);
1066 	}
1067 
1068 
1069 	/* \o -- set query output */
1070 	else if (strcmp(cmd, "o") == 0 || strcmp(cmd, "out") == 0)
1071 	{
1072 		char	   *fname = psql_scan_slash_option(scan_state,
1073 												   OT_FILEPIPE, NULL, true);
1074 
1075 		expand_tilde(&fname);
1076 		success = setQFout(fname);
1077 		free(fname);
1078 	}
1079 
1080 	/* \p prints the current query buffer */
1081 	else if (strcmp(cmd, "p") == 0 || strcmp(cmd, "print") == 0)
1082 	{
1083 		if (query_buf && query_buf->len > 0)
1084 			puts(query_buf->data);
1085 		else if (!pset.quiet)
1086 			puts(_("Query buffer is empty."));
1087 		fflush(stdout);
1088 	}
1089 
1090 	/* \password -- set user password */
1091 	else if (strcmp(cmd, "password") == 0)
1092 	{
1093 		char	   *pw1;
1094 		char	   *pw2;
1095 
1096 		pw1 = simple_prompt("Enter new password: ", 100, false);
1097 		pw2 = simple_prompt("Enter it again: ", 100, false);
1098 
1099 		if (strcmp(pw1, pw2) != 0)
1100 		{
1101 			psql_error("Passwords didn't match.\n");
1102 			success = false;
1103 		}
1104 		else
1105 		{
1106 			char	   *opt0 = psql_scan_slash_option(scan_state, OT_SQLID, NULL, true);
1107 			char	   *user;
1108 			char	   *encrypted_password;
1109 
1110 			if (opt0)
1111 				user = opt0;
1112 			else
1113 				user = PQuser(pset.db);
1114 
1115 			encrypted_password = PQencryptPassword(pw1, user);
1116 
1117 			if (!encrypted_password)
1118 			{
1119 				psql_error("Password encryption failed.\n");
1120 				success = false;
1121 			}
1122 			else
1123 			{
1124 				PQExpBufferData buf;
1125 				PGresult   *res;
1126 
1127 				initPQExpBuffer(&buf);
1128 				printfPQExpBuffer(&buf, "ALTER USER %s PASSWORD ",
1129 								  fmtId(user));
1130 				appendStringLiteralConn(&buf, encrypted_password, pset.db);
1131 				res = PSQLexec(buf.data);
1132 				termPQExpBuffer(&buf);
1133 				if (!res)
1134 					success = false;
1135 				else
1136 					PQclear(res);
1137 				PQfreemem(encrypted_password);
1138 			}
1139 
1140 			if (opt0)
1141 				free(opt0);
1142 		}
1143 
1144 		free(pw1);
1145 		free(pw2);
1146 	}
1147 
1148 	/* \prompt -- prompt and set variable */
1149 	else if (strcmp(cmd, "prompt") == 0)
1150 	{
1151 		char	   *opt,
1152 				   *prompt_text = NULL;
1153 		char	   *arg1,
1154 				   *arg2;
1155 
1156 		arg1 = psql_scan_slash_option(scan_state, OT_NORMAL, NULL, false);
1157 		arg2 = psql_scan_slash_option(scan_state, OT_NORMAL, NULL, false);
1158 
1159 		if (!arg1)
1160 		{
1161 			psql_error("\\%s: missing required argument\n", cmd);
1162 			success = false;
1163 		}
1164 		else
1165 		{
1166 			char	   *result;
1167 
1168 			if (arg2)
1169 			{
1170 				prompt_text = arg1;
1171 				opt = arg2;
1172 			}
1173 			else
1174 				opt = arg1;
1175 
1176 			if (!pset.inputfile)
1177 				result = simple_prompt(prompt_text, 4096, true);
1178 			else
1179 			{
1180 				if (prompt_text)
1181 				{
1182 					fputs(prompt_text, stdout);
1183 					fflush(stdout);
1184 				}
1185 				result = gets_fromFile(stdin);
1186 			}
1187 
1188 			if (!SetVariable(pset.vars, opt, result))
1189 			{
1190 				psql_error("\\%s: error while setting variable\n", cmd);
1191 				success = false;
1192 			}
1193 
1194 			free(result);
1195 			if (prompt_text)
1196 				free(prompt_text);
1197 			free(opt);
1198 		}
1199 	}
1200 
1201 	/* \pset -- set printing parameters */
1202 	else if (strcmp(cmd, "pset") == 0)
1203 	{
1204 		char	   *opt0 = psql_scan_slash_option(scan_state,
1205 												  OT_NORMAL, NULL, false);
1206 		char	   *opt1 = psql_scan_slash_option(scan_state,
1207 												  OT_NORMAL, NULL, false);
1208 
1209 		if (!opt0)
1210 		{
1211 			/* list all variables */
1212 
1213 			int			i;
1214 			static const char *const my_list[] = {
1215 				"border", "columns", "expanded", "fieldsep", "fieldsep_zero",
1216 				"footer", "format", "linestyle", "null",
1217 				"numericlocale", "pager", "pager_min_lines",
1218 				"recordsep", "recordsep_zero",
1219 				"tableattr", "title", "tuples_only",
1220 				"unicode_border_linestyle",
1221 				"unicode_column_linestyle",
1222 				"unicode_header_linestyle",
1223 				NULL
1224 			};
1225 
1226 			for (i = 0; my_list[i] != NULL; i++)
1227 			{
1228 				char	   *val = pset_value_string(my_list[i], &pset.popt);
1229 
1230 				printf("%-24s %s\n", my_list[i], val);
1231 				free(val);
1232 			}
1233 
1234 			success = true;
1235 		}
1236 		else
1237 			success = do_pset(opt0, opt1, &pset.popt, pset.quiet);
1238 
1239 		free(opt0);
1240 		free(opt1);
1241 	}
1242 
1243 	/* \q or \quit */
1244 	else if (strcmp(cmd, "q") == 0 || strcmp(cmd, "quit") == 0)
1245 		status = PSQL_CMD_TERMINATE;
1246 
1247 	/* reset(clear) the buffer */
1248 	else if (strcmp(cmd, "r") == 0 || strcmp(cmd, "reset") == 0)
1249 	{
1250 		resetPQExpBuffer(query_buf);
1251 		psql_scan_reset(scan_state);
1252 		if (!pset.quiet)
1253 			puts(_("Query buffer reset (cleared)."));
1254 	}
1255 
1256 	/* \s save history in a file or show it on the screen */
1257 	else if (strcmp(cmd, "s") == 0)
1258 	{
1259 		char	   *fname = psql_scan_slash_option(scan_state,
1260 												   OT_NORMAL, NULL, true);
1261 
1262 		expand_tilde(&fname);
1263 		success = printHistory(fname, pset.popt.topt.pager);
1264 		if (success && !pset.quiet && fname)
1265 			printf(_("Wrote history to file \"%s\".\n"), fname);
1266 		if (!fname)
1267 			putchar('\n');
1268 		free(fname);
1269 	}
1270 
1271 	/* \set -- generalized set variable/option command */
1272 	else if (strcmp(cmd, "set") == 0)
1273 	{
1274 		char	   *opt0 = psql_scan_slash_option(scan_state,
1275 												  OT_NORMAL, NULL, false);
1276 
1277 		if (!opt0)
1278 		{
1279 			/* list all variables */
1280 			PrintVariables(pset.vars);
1281 			success = true;
1282 		}
1283 		else
1284 		{
1285 			/*
1286 			 * Set variable to the concatenation of the arguments.
1287 			 */
1288 			char	   *newval;
1289 			char	   *opt;
1290 
1291 			opt = psql_scan_slash_option(scan_state,
1292 										 OT_NORMAL, NULL, false);
1293 			newval = pg_strdup(opt ? opt : "");
1294 			free(opt);
1295 
1296 			while ((opt = psql_scan_slash_option(scan_state,
1297 												 OT_NORMAL, NULL, false)))
1298 			{
1299 				newval = pg_realloc(newval, strlen(newval) + strlen(opt) + 1);
1300 				strcat(newval, opt);
1301 				free(opt);
1302 			}
1303 
1304 			if (!SetVariable(pset.vars, opt0, newval))
1305 			{
1306 				psql_error("\\%s: error while setting variable\n", cmd);
1307 				success = false;
1308 			}
1309 			free(newval);
1310 		}
1311 		free(opt0);
1312 	}
1313 
1314 
1315 	/* \setenv -- set environment command */
1316 	else if (strcmp(cmd, "setenv") == 0)
1317 	{
1318 		char	   *envvar = psql_scan_slash_option(scan_state,
1319 													OT_NORMAL, NULL, false);
1320 		char	   *envval = psql_scan_slash_option(scan_state,
1321 													OT_NORMAL, NULL, false);
1322 
1323 		if (!envvar)
1324 		{
1325 			psql_error("\\%s: missing required argument\n", cmd);
1326 			success = false;
1327 		}
1328 		else if (strchr(envvar, '=') != NULL)
1329 		{
1330 			psql_error("\\%s: environment variable name must not contain \"=\"\n",
1331 					   cmd);
1332 			success = false;
1333 		}
1334 		else if (!envval)
1335 		{
1336 			/* No argument - unset the environment variable */
1337 			unsetenv(envvar);
1338 			success = true;
1339 		}
1340 		else
1341 		{
1342 			/* Set variable to the value of the next argument */
1343 			char	   *newval;
1344 
1345 			newval = psprintf("%s=%s", envvar, envval);
1346 			putenv(newval);
1347 			success = true;
1348 
1349 			/*
1350 			 * Do not free newval here, it will screw up the environment if
1351 			 * you do. See putenv man page for details. That means we leak a
1352 			 * bit of memory here, but not enough to worry about.
1353 			 */
1354 		}
1355 		free(envvar);
1356 		free(envval);
1357 	}
1358 
1359 	/* \sf -- show a function's source code */
1360 	else if (strcmp(cmd, "sf") == 0 || strcmp(cmd, "sf+") == 0)
1361 	{
1362 		bool		show_linenumbers = (strcmp(cmd, "sf+") == 0);
1363 		PQExpBuffer func_buf;
1364 		char	   *func;
1365 		Oid			foid = InvalidOid;
1366 
1367 		func_buf = createPQExpBuffer();
1368 		func = psql_scan_slash_option(scan_state,
1369 									  OT_WHOLE_LINE, NULL, true);
1370 		if (pset.sversion < 80400)
1371 		{
1372 			char		sverbuf[32];
1373 
1374 			psql_error("The server (version %s) does not support showing function source.\n",
1375 					   formatPGVersionNumber(pset.sversion, false,
1376 											 sverbuf, sizeof(sverbuf)));
1377 			status = PSQL_CMD_ERROR;
1378 		}
1379 		else if (!func)
1380 		{
1381 			psql_error("function name is required\n");
1382 			status = PSQL_CMD_ERROR;
1383 		}
1384 		else if (!lookup_object_oid(EditableFunction, func, &foid))
1385 		{
1386 			/* error already reported */
1387 			status = PSQL_CMD_ERROR;
1388 		}
1389 		else if (!get_create_object_cmd(EditableFunction, foid, func_buf))
1390 		{
1391 			/* error already reported */
1392 			status = PSQL_CMD_ERROR;
1393 		}
1394 		else
1395 		{
1396 			FILE	   *output;
1397 			bool		is_pager;
1398 
1399 			/* Select output stream: stdout, pager, or file */
1400 			if (pset.queryFout == stdout)
1401 			{
1402 				/* count lines in function to see if pager is needed */
1403 				int			lineno = count_lines_in_buf(func_buf);
1404 
1405 				output = PageOutput(lineno, &(pset.popt.topt));
1406 				is_pager = true;
1407 			}
1408 			else
1409 			{
1410 				/* use previously set output file, without pager */
1411 				output = pset.queryFout;
1412 				is_pager = false;
1413 			}
1414 
1415 			if (show_linenumbers)
1416 			{
1417 				/*
1418 				 * lineno "1" should correspond to the first line of the
1419 				 * function body.  We expect that pg_get_functiondef() will
1420 				 * emit that on a line beginning with "AS ", and that there
1421 				 * can be no such line before the real start of the function
1422 				 * body.
1423 				 */
1424 				print_with_linenumbers(output, func_buf->data, "AS ");
1425 			}
1426 			else
1427 			{
1428 				/* just send the function definition to output */
1429 				fputs(func_buf->data, output);
1430 			}
1431 
1432 			if (is_pager)
1433 				ClosePager(output);
1434 		}
1435 
1436 		if (func)
1437 			free(func);
1438 		destroyPQExpBuffer(func_buf);
1439 	}
1440 
1441 	/* \sv -- show a view's source code */
1442 	else if (strcmp(cmd, "sv") == 0 || strcmp(cmd, "sv+") == 0)
1443 	{
1444 		bool		show_linenumbers = (strcmp(cmd, "sv+") == 0);
1445 		PQExpBuffer view_buf;
1446 		char	   *view;
1447 		Oid			view_oid = InvalidOid;
1448 
1449 		view_buf = createPQExpBuffer();
1450 		view = psql_scan_slash_option(scan_state,
1451 									  OT_WHOLE_LINE, NULL, true);
1452 		if (pset.sversion < 70400)
1453 		{
1454 			char		sverbuf[32];
1455 
1456 			psql_error("The server (version %s) does not support showing view definitions.\n",
1457 					   formatPGVersionNumber(pset.sversion, false,
1458 											 sverbuf, sizeof(sverbuf)));
1459 			status = PSQL_CMD_ERROR;
1460 		}
1461 		else if (!view)
1462 		{
1463 			psql_error("view name is required\n");
1464 			status = PSQL_CMD_ERROR;
1465 		}
1466 		else if (!lookup_object_oid(EditableView, view, &view_oid))
1467 		{
1468 			/* error already reported */
1469 			status = PSQL_CMD_ERROR;
1470 		}
1471 		else if (!get_create_object_cmd(EditableView, view_oid, view_buf))
1472 		{
1473 			/* error already reported */
1474 			status = PSQL_CMD_ERROR;
1475 		}
1476 		else
1477 		{
1478 			FILE	   *output;
1479 			bool		is_pager;
1480 
1481 			/* Select output stream: stdout, pager, or file */
1482 			if (pset.queryFout == stdout)
1483 			{
1484 				/* count lines in view to see if pager is needed */
1485 				int			lineno = count_lines_in_buf(view_buf);
1486 
1487 				output = PageOutput(lineno, &(pset.popt.topt));
1488 				is_pager = true;
1489 			}
1490 			else
1491 			{
1492 				/* use previously set output file, without pager */
1493 				output = pset.queryFout;
1494 				is_pager = false;
1495 			}
1496 
1497 			if (show_linenumbers)
1498 			{
1499 				/* add line numbers, numbering all lines */
1500 				print_with_linenumbers(output, view_buf->data, NULL);
1501 			}
1502 			else
1503 			{
1504 				/* just send the view definition to output */
1505 				fputs(view_buf->data, output);
1506 			}
1507 
1508 			if (is_pager)
1509 				ClosePager(output);
1510 		}
1511 
1512 		if (view)
1513 			free(view);
1514 		destroyPQExpBuffer(view_buf);
1515 	}
1516 
1517 	/* \t -- turn off headers and row count */
1518 	else if (strcmp(cmd, "t") == 0)
1519 	{
1520 		char	   *opt = psql_scan_slash_option(scan_state,
1521 												 OT_NORMAL, NULL, true);
1522 
1523 		success = do_pset("tuples_only", opt, &pset.popt, pset.quiet);
1524 		free(opt);
1525 	}
1526 
1527 	/* \T -- define html <table ...> attributes */
1528 	else if (strcmp(cmd, "T") == 0)
1529 	{
1530 		char	   *value = psql_scan_slash_option(scan_state,
1531 												   OT_NORMAL, NULL, false);
1532 
1533 		success = do_pset("tableattr", value, &pset.popt, pset.quiet);
1534 		free(value);
1535 	}
1536 
1537 	/* \timing -- toggle timing of queries */
1538 	else if (strcmp(cmd, "timing") == 0)
1539 	{
1540 		char	   *opt = psql_scan_slash_option(scan_state,
1541 												 OT_NORMAL, NULL, false);
1542 
1543 		if (opt)
1544 			pset.timing = ParseVariableBool(opt, "\\timing");
1545 		else
1546 			pset.timing = !pset.timing;
1547 		if (!pset.quiet)
1548 		{
1549 			if (pset.timing)
1550 				puts(_("Timing is on."));
1551 			else
1552 				puts(_("Timing is off."));
1553 		}
1554 		free(opt);
1555 	}
1556 
1557 	/* \unset */
1558 	else if (strcmp(cmd, "unset") == 0)
1559 	{
1560 		char	   *opt = psql_scan_slash_option(scan_state,
1561 												 OT_NORMAL, NULL, false);
1562 
1563 		if (!opt)
1564 		{
1565 			psql_error("\\%s: missing required argument\n", cmd);
1566 			success = false;
1567 		}
1568 		else if (!SetVariable(pset.vars, opt, NULL))
1569 		{
1570 			psql_error("\\%s: error while setting variable\n", cmd);
1571 			success = false;
1572 		}
1573 		free(opt);
1574 	}
1575 
1576 	/* \w -- write query buffer to file */
1577 	else if (strcmp(cmd, "w") == 0 || strcmp(cmd, "write") == 0)
1578 	{
1579 		FILE	   *fd = NULL;
1580 		bool		is_pipe = false;
1581 		char	   *fname = NULL;
1582 
1583 		if (!query_buf)
1584 		{
1585 			psql_error("no query buffer\n");
1586 			status = PSQL_CMD_ERROR;
1587 		}
1588 		else
1589 		{
1590 			fname = psql_scan_slash_option(scan_state,
1591 										   OT_FILEPIPE, NULL, true);
1592 			expand_tilde(&fname);
1593 
1594 			if (!fname)
1595 			{
1596 				psql_error("\\%s: missing required argument\n", cmd);
1597 				success = false;
1598 			}
1599 			else
1600 			{
1601 				if (fname[0] == '|')
1602 				{
1603 					is_pipe = true;
1604 					disable_sigpipe_trap();
1605 					fd = popen(&fname[1], "w");
1606 				}
1607 				else
1608 				{
1609 					canonicalize_path(fname);
1610 					fd = fopen(fname, "w");
1611 				}
1612 				if (!fd)
1613 				{
1614 					psql_error("%s: %s\n", fname, strerror(errno));
1615 					success = false;
1616 				}
1617 			}
1618 		}
1619 
1620 		if (fd)
1621 		{
1622 			int			result;
1623 
1624 			if (query_buf && query_buf->len > 0)
1625 				fprintf(fd, "%s\n", query_buf->data);
1626 
1627 			if (is_pipe)
1628 				result = pclose(fd);
1629 			else
1630 				result = fclose(fd);
1631 
1632 			if (result == EOF)
1633 			{
1634 				psql_error("%s: %s\n", fname, strerror(errno));
1635 				success = false;
1636 			}
1637 		}
1638 
1639 		if (is_pipe)
1640 			restore_sigpipe_trap();
1641 
1642 		free(fname);
1643 	}
1644 
1645 	/* \watch -- execute a query every N seconds */
1646 	else if (strcmp(cmd, "watch") == 0)
1647 	{
1648 		char	   *opt = psql_scan_slash_option(scan_state,
1649 												 OT_NORMAL, NULL, true);
1650 		double		sleep = 2;
1651 
1652 		/* Convert optional sleep-length argument */
1653 		if (opt)
1654 		{
1655 			sleep = strtod(opt, NULL);
1656 			if (sleep <= 0)
1657 				sleep = 1;
1658 			free(opt);
1659 		}
1660 
1661 		success = do_watch(query_buf, sleep);
1662 
1663 		/* Reset the query buffer as though for \r */
1664 		resetPQExpBuffer(query_buf);
1665 		psql_scan_reset(scan_state);
1666 	}
1667 
1668 	/* \x -- set or toggle expanded table representation */
1669 	else if (strcmp(cmd, "x") == 0)
1670 	{
1671 		char	   *opt = psql_scan_slash_option(scan_state,
1672 												 OT_NORMAL, NULL, true);
1673 
1674 		success = do_pset("expanded", opt, &pset.popt, pset.quiet);
1675 		free(opt);
1676 	}
1677 
1678 	/* \z -- list table rights (equivalent to \dp) */
1679 	else if (strcmp(cmd, "z") == 0)
1680 	{
1681 		char	   *pattern = psql_scan_slash_option(scan_state,
1682 													 OT_NORMAL, NULL, true);
1683 
1684 		success = permissionsList(pattern);
1685 		if (pattern)
1686 			free(pattern);
1687 	}
1688 
1689 	/* \! -- shell escape */
1690 	else if (strcmp(cmd, "!") == 0)
1691 	{
1692 		char	   *opt = psql_scan_slash_option(scan_state,
1693 												 OT_WHOLE_LINE, NULL, false);
1694 
1695 		success = do_shell(opt);
1696 		free(opt);
1697 	}
1698 
1699 	/* \? -- slash command help */
1700 	else if (strcmp(cmd, "?") == 0)
1701 	{
1702 		char	   *opt0 = psql_scan_slash_option(scan_state,
1703 												  OT_NORMAL, NULL, false);
1704 
1705 		if (!opt0 || strcmp(opt0, "commands") == 0)
1706 			slashUsage(pset.popt.topt.pager);
1707 		else if (strcmp(opt0, "options") == 0)
1708 			usage(pset.popt.topt.pager);
1709 		else if (strcmp(opt0, "variables") == 0)
1710 			helpVariables(pset.popt.topt.pager);
1711 		else
1712 			slashUsage(pset.popt.topt.pager);
1713 	}
1714 
1715 #if 0
1716 
1717 	/*
1718 	 * These commands don't do anything. I just use them to test the parser.
1719 	 */
1720 	else if (strcmp(cmd, "void") == 0 || strcmp(cmd, "#") == 0)
1721 	{
1722 		int			i = 0;
1723 		char	   *value;
1724 
1725 		while ((value = psql_scan_slash_option(scan_state,
1726 											   OT_NORMAL, NULL, true)))
1727 		{
1728 			psql_error("+ opt(%d) = |%s|\n", i++, value);
1729 			free(value);
1730 		}
1731 	}
1732 #endif
1733 
1734 	else
1735 		status = PSQL_CMD_UNKNOWN;
1736 
1737 	if (!success)
1738 		status = PSQL_CMD_ERROR;
1739 
1740 	return status;
1741 }
1742 
1743 /*
1744  * Ask the user for a password; 'username' is the username the
1745  * password is for, if one has been explicitly specified. Returns a
1746  * malloc'd string.
1747  */
1748 static char *
prompt_for_password(const char * username)1749 prompt_for_password(const char *username)
1750 {
1751 	char	   *result;
1752 
1753 	if (username == NULL)
1754 		result = simple_prompt("Password: ", 100, false);
1755 	else
1756 	{
1757 		char	   *prompt_text;
1758 
1759 		prompt_text = psprintf(_("Password for user %s: "), username);
1760 		result = simple_prompt(prompt_text, 100, false);
1761 		free(prompt_text);
1762 	}
1763 
1764 	return result;
1765 }
1766 
1767 static bool
param_is_newly_set(const char * old_val,const char * new_val)1768 param_is_newly_set(const char *old_val, const char *new_val)
1769 {
1770 	if (new_val == NULL)
1771 		return false;
1772 
1773 	if (old_val == NULL || strcmp(old_val, new_val) != 0)
1774 		return true;
1775 
1776 	return false;
1777 }
1778 
1779 /*
1780  * do_connect -- handler for \connect
1781  *
1782  * Connects to a database with given parameters. Absent an established
1783  * connection, all parameters are required. Given -reuse-previous=off or a
1784  * connection string without -reuse-previous=on, NULL values will pass through
1785  * to PQconnectdbParams(), so the libpq defaults will be used. Otherwise, NULL
1786  * values will be replaced with the ones in the current connection.
1787  *
1788  * In interactive mode, if connection fails with the given parameters,
1789  * the old connection will be kept.
1790  */
1791 static bool
do_connect(enum trivalue reuse_previous_specification,char * dbname,char * user,char * host,char * port)1792 do_connect(enum trivalue reuse_previous_specification,
1793 		   char *dbname, char *user, char *host, char *port)
1794 {
1795 	PGconn	   *o_conn = pset.db,
1796 			   *n_conn = NULL;
1797 	PQconninfoOption *cinfo;
1798 	int			nconnopts = 0;
1799 	bool		same_host = false;
1800 	char	   *password = NULL;
1801 	char	   *client_encoding;
1802 	bool		success = true;
1803 	bool		keep_password = true;
1804 	bool		has_connection_string;
1805 	bool		reuse_previous;
1806 
1807 	if (!o_conn && (!dbname || !user || !host || !port))
1808 	{
1809 		/*
1810 		 * We don't know the supplied connection parameters and don't want to
1811 		 * connect to the wrong database by using defaults, so require all
1812 		 * parameters to be specified.
1813 		 */
1814 		psql_error("All connection parameters must be supplied because no "
1815 				   "database connection exists\n");
1816 		return false;
1817 	}
1818 
1819 	has_connection_string = dbname ?
1820 		recognized_connection_string(dbname) : false;
1821 	switch (reuse_previous_specification)
1822 	{
1823 		case TRI_YES:
1824 			reuse_previous = true;
1825 			break;
1826 		case TRI_NO:
1827 			reuse_previous = false;
1828 			break;
1829 		default:
1830 			reuse_previous = !has_connection_string;
1831 			break;
1832 	}
1833 
1834 	/* If the old connection does not exist, there is nothing to reuse. */
1835 	if (!o_conn)
1836 		reuse_previous = false;
1837 
1838 	/* Silently ignore arguments subsequent to a connection string. */
1839 	if (has_connection_string)
1840 	{
1841 		user = NULL;
1842 		host = NULL;
1843 		port = NULL;
1844 	}
1845 
1846 	/*
1847 	 * If we intend to re-use connection parameters, collect them out of the
1848 	 * old connection, then replace individual values as necessary. Otherwise,
1849 	 * obtain a PQconninfoOption array containing libpq's defaults, and modify
1850 	 * that.  Note this function assumes that PQconninfo, PQconndefaults, and
1851 	 * PQconninfoParse will all produce arrays containing the same options in
1852 	 * the same order.
1853 	 */
1854 	if (reuse_previous)
1855 		cinfo = PQconninfo(o_conn);
1856 	else
1857 		cinfo = PQconndefaults();
1858 
1859 	if (cinfo)
1860 	{
1861 		if (has_connection_string)
1862 		{
1863 			/* Parse the connstring and insert values into cinfo */
1864 			PQconninfoOption *replcinfo;
1865 			char	   *errmsg;
1866 
1867 			replcinfo = PQconninfoParse(dbname, &errmsg);
1868 			if (replcinfo)
1869 			{
1870 				PQconninfoOption *ci;
1871 				PQconninfoOption *replci;
1872 				bool		have_password = false;
1873 
1874 				for (ci = cinfo, replci = replcinfo;
1875 					 ci->keyword && replci->keyword;
1876 					 ci++, replci++)
1877 				{
1878 					Assert(strcmp(ci->keyword, replci->keyword) == 0);
1879 					/* Insert value from connstring if one was provided */
1880 					if (replci->val)
1881 					{
1882 						/*
1883 						 * We know that both val strings were allocated by
1884 						 * libpq, so the least messy way to avoid memory leaks
1885 						 * is to swap them.
1886 						 */
1887 						char	   *swap = replci->val;
1888 
1889 						replci->val = ci->val;
1890 						ci->val = swap;
1891 
1892 						/*
1893 						 * Check whether connstring provides options affecting
1894 						 * password re-use.  While any change in user, host,
1895 						 * hostaddr, or port causes us to ignore the old
1896 						 * connection's password, we don't force that for
1897 						 * dbname, since passwords aren't database-specific.
1898 						 */
1899 						if (replci->val == NULL ||
1900 							strcmp(ci->val, replci->val) != 0)
1901 						{
1902 							if (strcmp(replci->keyword, "user") == 0 ||
1903 								strcmp(replci->keyword, "host") == 0 ||
1904 								strcmp(replci->keyword, "hostaddr") == 0 ||
1905 								strcmp(replci->keyword, "port") == 0)
1906 								keep_password = false;
1907 						}
1908 						/* Also note whether connstring contains a password. */
1909 						if (strcmp(replci->keyword, "password") == 0)
1910 							have_password = true;
1911 					}
1912 					else if (!reuse_previous)
1913 					{
1914 						/*
1915 						 * When we have a connstring and are not re-using
1916 						 * parameters, swap *all* entries, even those not set
1917 						 * by the connstring.  This avoids absorbing
1918 						 * environment-dependent defaults from the result of
1919 						 * PQconndefaults().  We don't want to do that because
1920 						 * they'd override service-file entries if the
1921 						 * connstring specifies a service parameter, whereas
1922 						 * the priority should be the other way around.  libpq
1923 						 * can certainly recompute any defaults we don't pass
1924 						 * here.  (In this situation, it's a bit wasteful to
1925 						 * have called PQconndefaults() at all, but not doing
1926 						 * so would require yet another major code path here.)
1927 						 */
1928 						replci->val = ci->val;
1929 						ci->val = NULL;
1930 					}
1931 				}
1932 				Assert(ci->keyword == NULL && replci->keyword == NULL);
1933 
1934 				/* While here, determine how many option slots there are */
1935 				nconnopts = ci - cinfo;
1936 
1937 				PQconninfoFree(replcinfo);
1938 
1939 				/*
1940 				 * If the connstring contains a password, tell the loop below
1941 				 * that we may use it, regardless of other settings (i.e.,
1942 				 * cinfo's password is no longer an "old" password).
1943 				 */
1944 				if (have_password)
1945 					keep_password = true;
1946 
1947 				/* Don't let code below try to inject dbname into params. */
1948 				dbname = NULL;
1949 			}
1950 			else
1951 			{
1952 				/* PQconninfoParse failed */
1953 				if (errmsg)
1954 				{
1955 					psql_error("%s", errmsg);
1956 					PQfreemem(errmsg);
1957 				}
1958 				else
1959 					psql_error("out of memory\n");
1960 				success = false;
1961 			}
1962 		}
1963 		else
1964 		{
1965 			/*
1966 			 * If dbname isn't a connection string, then we'll inject it and
1967 			 * the other parameters into the keyword array below.  (We can't
1968 			 * easily insert them into the cinfo array because of memory
1969 			 * management issues: PQconninfoFree would misbehave on Windows.)
1970 			 * However, to avoid dependencies on the order in which parameters
1971 			 * appear in the array, make a preliminary scan to set
1972 			 * keep_password and same_host correctly.
1973 			 *
1974 			 * While any change in user, host, or port causes us to ignore the
1975 			 * old connection's password, we don't force that for dbname,
1976 			 * since passwords aren't database-specific.
1977 			 */
1978 			PQconninfoOption *ci;
1979 
1980 			for (ci = cinfo; ci->keyword; ci++)
1981 			{
1982 				if (user && strcmp(ci->keyword, "user") == 0)
1983 				{
1984 					if (!(ci->val && strcmp(user, ci->val) == 0))
1985 						keep_password = false;
1986 				}
1987 				else if (host && strcmp(ci->keyword, "host") == 0)
1988 				{
1989 					if (ci->val && strcmp(host, ci->val) == 0)
1990 						same_host = true;
1991 					else
1992 						keep_password = false;
1993 				}
1994 				else if (port && strcmp(ci->keyword, "port") == 0)
1995 				{
1996 					if (!(ci->val && strcmp(port, ci->val) == 0))
1997 						keep_password = false;
1998 				}
1999 			}
2000 
2001 			/* While here, determine how many option slots there are */
2002 			nconnopts = ci - cinfo;
2003 		}
2004 	}
2005 	else
2006 	{
2007 		/* We failed to create the cinfo structure */
2008 		psql_error("out of memory\n");
2009 		success = false;
2010 	}
2011 
2012 	/*
2013 	 * If the user asked to be prompted for a password, ask for one now. If
2014 	 * not, use the password from the old connection, provided the username
2015 	 * etc have not changed. Otherwise, try to connect without a password
2016 	 * first, and then ask for a password if needed.
2017 	 *
2018 	 * XXX: this behavior leads to spurious connection attempts recorded in
2019 	 * the postmaster's log.  But libpq offers no API that would let us obtain
2020 	 * a password and then continue with the first connection attempt.
2021 	 */
2022 	if (pset.getPassword == TRI_YES && success)
2023 	{
2024 		password = prompt_for_password(user);
2025 	}
2026 
2027 	/*
2028 	 * Consider whether to force client_encoding to "auto" (overriding
2029 	 * anything in the connection string).  We do so if we have a terminal
2030 	 * connection and there is no PGCLIENTENCODING environment setting.
2031 	 */
2032 	if (pset.notty || getenv("PGCLIENTENCODING"))
2033 		client_encoding = NULL;
2034 	else
2035 		client_encoding = "auto";
2036 
2037 	/* Loop till we have a connection or fail, which we might've already */
2038 	while (success)
2039 	{
2040 		const char **keywords = pg_malloc((nconnopts + 1) * sizeof(*keywords));
2041 		const char **values = pg_malloc((nconnopts + 1) * sizeof(*values));
2042 		int			paramnum = 0;
2043 		PQconninfoOption *ci;
2044 
2045 		/*
2046 		 * Copy non-default settings into the PQconnectdbParams parameter
2047 		 * arrays; but inject any values specified old-style, as well as any
2048 		 * interactively-obtained password, and a couple of fields we want to
2049 		 * set forcibly.
2050 		 *
2051 		 * If you change this code, see also the initial-connection code in
2052 		 * main().
2053 		 */
2054 		for (ci = cinfo; ci->keyword; ci++)
2055 		{
2056 			keywords[paramnum] = ci->keyword;
2057 
2058 			if (dbname && strcmp(ci->keyword, "dbname") == 0)
2059 				values[paramnum++] = dbname;
2060 			else if (user && strcmp(ci->keyword, "user") == 0)
2061 				values[paramnum++] = user;
2062 			else if (host && strcmp(ci->keyword, "host") == 0)
2063 				values[paramnum++] = host;
2064 			else if (host && !same_host && strcmp(ci->keyword, "hostaddr") == 0)
2065 			{
2066 				/* If we're changing the host value, drop any old hostaddr */
2067 				values[paramnum++] = NULL;
2068 			}
2069 			else if (port && strcmp(ci->keyword, "port") == 0)
2070 				values[paramnum++] = port;
2071 			/* If !keep_password, we unconditionally drop old password */
2072 			else if ((password || !keep_password) &&
2073 					 strcmp(ci->keyword, "password") == 0)
2074 				values[paramnum++] = password;
2075 			else if (strcmp(ci->keyword, "fallback_application_name") == 0)
2076 				values[paramnum++] = pset.progname;
2077 			else if (client_encoding &&
2078 					 strcmp(ci->keyword, "client_encoding") == 0)
2079 				values[paramnum++] = client_encoding;
2080 			else if (ci->val)
2081 				values[paramnum++] = ci->val;
2082 			/* else, don't bother making libpq parse this keyword */
2083 		}
2084 		/* add array terminator */
2085 		keywords[paramnum] = NULL;
2086 		values[paramnum] = NULL;
2087 
2088 		/* Note we do not want libpq to re-expand the dbname parameter */
2089 		n_conn = PQconnectdbParams(keywords, values, false);
2090 
2091 		pg_free(keywords);
2092 		pg_free(values);
2093 
2094 		if (PQstatus(n_conn) == CONNECTION_OK)
2095 			break;
2096 
2097 		/*
2098 		 * Connection attempt failed; either retry the connection attempt with
2099 		 * a new password, or give up.
2100 		 */
2101 		if (!password && PQconnectionNeedsPassword(n_conn) && pset.getPassword != TRI_NO)
2102 		{
2103 			/*
2104 			 * Prompt for password using the username we actually connected
2105 			 * with --- it might've come out of "dbname" rather than "user".
2106 			 */
2107 			password = prompt_for_password(PQuser(n_conn));
2108 			PQfinish(n_conn);
2109 			n_conn = NULL;
2110 			continue;
2111 		}
2112 
2113 		/*
2114 		 * We'll report the error below ... unless n_conn is NULL, indicating
2115 		 * that libpq didn't have enough memory to make a PGconn.
2116 		 */
2117 		if (n_conn == NULL)
2118 			psql_error("out of memory\n");
2119 
2120 		success = false;
2121 	}							/* end retry loop */
2122 
2123 	/* Release locally allocated data, whether we succeeded or not */
2124 	if (password)
2125 		pg_free(password);
2126 	if (cinfo)
2127 		PQconninfoFree(cinfo);
2128 
2129 	if (!success)
2130 	{
2131 		/*
2132 		 * Failed to connect to the database. In interactive mode, keep the
2133 		 * previous connection to the DB; in scripting mode, close our
2134 		 * previous connection as well.
2135 		 */
2136 		if (pset.cur_cmd_interactive)
2137 		{
2138 			if (n_conn)
2139 			{
2140 				psql_error("%s", PQerrorMessage(n_conn));
2141 				PQfinish(n_conn);
2142 			}
2143 
2144 			/* pset.db is left unmodified */
2145 			if (o_conn)
2146 				psql_error("Previous connection kept\n");
2147 		}
2148 		else
2149 		{
2150 			if (n_conn)
2151 			{
2152 				psql_error("\\connect: %s", PQerrorMessage(n_conn));
2153 				PQfinish(n_conn);
2154 			}
2155 
2156 			if (o_conn)
2157 			{
2158 				/*
2159 				 * Transition to having no connection.  Keep this bit in sync
2160 				 * with CheckConnection().
2161 				 */
2162 				PQfinish(o_conn);
2163 				pset.db = NULL;
2164 				ResetCancelConn();
2165 				UnsyncVariables();
2166 			}
2167 		}
2168 
2169 		return false;
2170 	}
2171 
2172 	/*
2173 	 * Replace the old connection with the new one, and update
2174 	 * connection-dependent variables.  Keep the resynchronization logic in
2175 	 * sync with CheckConnection().
2176 	 */
2177 	PQsetNoticeProcessor(n_conn, NoticeProcessor, NULL);
2178 	pset.db = n_conn;
2179 	SyncVariables();
2180 	connection_warnings(false); /* Must be after SyncVariables */
2181 
2182 	/* Tell the user about the new connection */
2183 	if (!pset.quiet)
2184 	{
2185 		if (!o_conn ||
2186 			param_is_newly_set(PQhost(o_conn), PQhost(pset.db)) ||
2187 			param_is_newly_set(PQport(o_conn), PQport(pset.db)))
2188 		{
2189 			char	   *host = PQhost(pset.db);
2190 
2191 			/* If the host is an absolute path, the connection is via socket */
2192 			if (is_absolute_path(host))
2193 				printf(_("You are now connected to database \"%s\" as user \"%s\" via socket in \"%s\" at port \"%s\".\n"),
2194 					   PQdb(pset.db), PQuser(pset.db), host, PQport(pset.db));
2195 			else
2196 				printf(_("You are now connected to database \"%s\" as user \"%s\" on host \"%s\" at port \"%s\".\n"),
2197 					   PQdb(pset.db), PQuser(pset.db), host, PQport(pset.db));
2198 		}
2199 		else
2200 			printf(_("You are now connected to database \"%s\" as user \"%s\".\n"),
2201 				   PQdb(pset.db), PQuser(pset.db));
2202 	}
2203 
2204 	if (o_conn)
2205 		PQfinish(o_conn);
2206 	return true;
2207 }
2208 
2209 
2210 void
connection_warnings(bool in_startup)2211 connection_warnings(bool in_startup)
2212 {
2213 	if (!pset.quiet && !pset.notty)
2214 	{
2215 		int			client_ver = PG_VERSION_NUM;
2216 		char		cverbuf[32];
2217 		char		sverbuf[32];
2218 
2219 		if (pset.sversion != client_ver)
2220 		{
2221 			const char *server_version;
2222 
2223 			/* Try to get full text form, might include "devel" etc */
2224 			server_version = PQparameterStatus(pset.db, "server_version");
2225 			/* Otherwise fall back on pset.sversion */
2226 			if (!server_version)
2227 			{
2228 				formatPGVersionNumber(pset.sversion, true,
2229 									  sverbuf, sizeof(sverbuf));
2230 				server_version = sverbuf;
2231 			}
2232 
2233 			printf(_("%s (%s, server %s)\n"),
2234 				   pset.progname, PG_VERSION, server_version);
2235 		}
2236 		/* For version match, only print psql banner on startup. */
2237 		else if (in_startup)
2238 			printf("%s (%s)\n", pset.progname, PG_VERSION);
2239 
2240 		if (pset.sversion / 100 > client_ver / 100)
2241 			printf(_("WARNING: %s major version %s, server major version %s.\n"
2242 					 "         Some psql features might not work.\n"),
2243 				   pset.progname,
2244 				   formatPGVersionNumber(client_ver, false,
2245 										 cverbuf, sizeof(cverbuf)),
2246 				   formatPGVersionNumber(pset.sversion, false,
2247 										 sverbuf, sizeof(sverbuf)));
2248 
2249 #ifdef WIN32
2250 		if (in_startup)
2251 			checkWin32Codepage();
2252 #endif
2253 		printSSLInfo();
2254 	}
2255 }
2256 
2257 
2258 /*
2259  * printSSLInfo
2260  *
2261  * Prints information about the current SSL connection, if SSL is in use
2262  */
2263 static void
printSSLInfo(void)2264 printSSLInfo(void)
2265 {
2266 	const char *protocol;
2267 	const char *cipher;
2268 	const char *bits;
2269 	const char *compression;
2270 
2271 	if (!PQsslInUse(pset.db))
2272 		return;					/* no SSL */
2273 
2274 	protocol = PQsslAttribute(pset.db, "protocol");
2275 	cipher = PQsslAttribute(pset.db, "cipher");
2276 	bits = PQsslAttribute(pset.db, "key_bits");
2277 	compression = PQsslAttribute(pset.db, "compression");
2278 
2279 	printf(_("SSL connection (protocol: %s, cipher: %s, bits: %s, compression: %s)\n"),
2280 		   protocol ? protocol : _("unknown"),
2281 		   cipher ? cipher : _("unknown"),
2282 		   bits ? bits : _("unknown"),
2283 	  (compression && strcmp(compression, "off") != 0) ? _("on") : _("off"));
2284 }
2285 
2286 
2287 /*
2288  * checkWin32Codepage
2289  *
2290  * Prints a warning when win32 console codepage differs from Windows codepage
2291  */
2292 #ifdef WIN32
2293 static void
checkWin32Codepage(void)2294 checkWin32Codepage(void)
2295 {
2296 	unsigned int wincp,
2297 				concp;
2298 
2299 	wincp = GetACP();
2300 	concp = GetConsoleCP();
2301 	if (wincp != concp)
2302 	{
2303 		printf(_("WARNING: Console code page (%u) differs from Windows code page (%u)\n"
2304 				 "         8-bit characters might not work correctly. See psql reference\n"
2305 				 "         page \"Notes for Windows users\" for details.\n"),
2306 			   concp, wincp);
2307 	}
2308 }
2309 #endif
2310 
2311 
2312 /*
2313  * SyncVariables
2314  *
2315  * Make psql's internal variables agree with connection state upon
2316  * establishing a new connection.
2317  */
2318 void
SyncVariables(void)2319 SyncVariables(void)
2320 {
2321 	/* get stuff from connection */
2322 	pset.encoding = PQclientEncoding(pset.db);
2323 	pset.popt.topt.encoding = pset.encoding;
2324 	pset.sversion = PQserverVersion(pset.db);
2325 
2326 	SetVariable(pset.vars, "DBNAME", PQdb(pset.db));
2327 	SetVariable(pset.vars, "USER", PQuser(pset.db));
2328 	SetVariable(pset.vars, "HOST", PQhost(pset.db));
2329 	SetVariable(pset.vars, "PORT", PQport(pset.db));
2330 	SetVariable(pset.vars, "ENCODING", pg_encoding_to_char(pset.encoding));
2331 
2332 	/* send stuff to it, too */
2333 	PQsetErrorVerbosity(pset.db, pset.verbosity);
2334 	PQsetErrorContextVisibility(pset.db, pset.show_context);
2335 }
2336 
2337 /*
2338  * UnsyncVariables
2339  *
2340  * Clear variables that should be not be set when there is no connection.
2341  */
2342 void
UnsyncVariables(void)2343 UnsyncVariables(void)
2344 {
2345 	SetVariable(pset.vars, "DBNAME", NULL);
2346 	SetVariable(pset.vars, "USER", NULL);
2347 	SetVariable(pset.vars, "HOST", NULL);
2348 	SetVariable(pset.vars, "PORT", NULL);
2349 	SetVariable(pset.vars, "ENCODING", NULL);
2350 }
2351 
2352 
2353 /*
2354  * do_edit -- handler for \e
2355  *
2356  * If you do not specify a filename, the current query buffer will be copied
2357  * into a temporary one.
2358  */
2359 static bool
editFile(const char * fname,int lineno)2360 editFile(const char *fname, int lineno)
2361 {
2362 	const char *editorName;
2363 	const char *editor_lineno_arg = NULL;
2364 	char	   *sys;
2365 	int			result;
2366 
2367 	Assert(fname != NULL);
2368 
2369 	/* Find an editor to use */
2370 	editorName = getenv("PSQL_EDITOR");
2371 	if (!editorName)
2372 		editorName = getenv("EDITOR");
2373 	if (!editorName)
2374 		editorName = getenv("VISUAL");
2375 	if (!editorName)
2376 		editorName = DEFAULT_EDITOR;
2377 
2378 	/* Get line number argument, if we need it. */
2379 	if (lineno > 0)
2380 	{
2381 		editor_lineno_arg = getenv("PSQL_EDITOR_LINENUMBER_ARG");
2382 #ifdef DEFAULT_EDITOR_LINENUMBER_ARG
2383 		if (!editor_lineno_arg)
2384 			editor_lineno_arg = DEFAULT_EDITOR_LINENUMBER_ARG;
2385 #endif
2386 		if (!editor_lineno_arg)
2387 		{
2388 			psql_error("environment variable PSQL_EDITOR_LINENUMBER_ARG must be set to specify a line number\n");
2389 			return false;
2390 		}
2391 	}
2392 
2393 	/*
2394 	 * On Unix the EDITOR value should *not* be quoted, since it might include
2395 	 * switches, eg, EDITOR="pico -t"; it's up to the user to put quotes in it
2396 	 * if necessary.  But this policy is not very workable on Windows, due to
2397 	 * severe brain damage in their command shell plus the fact that standard
2398 	 * program paths include spaces.
2399 	 */
2400 #ifndef WIN32
2401 	if (lineno > 0)
2402 		sys = psprintf("exec %s %s%d '%s'",
2403 					   editorName, editor_lineno_arg, lineno, fname);
2404 	else
2405 		sys = psprintf("exec %s '%s'",
2406 					   editorName, fname);
2407 #else
2408 	if (lineno > 0)
2409 		sys = psprintf("\"%s\" %s%d \"%s\"",
2410 					   editorName, editor_lineno_arg, lineno, fname);
2411 	else
2412 		sys = psprintf("\"%s\" \"%s\"",
2413 					   editorName, fname);
2414 #endif
2415 	result = system(sys);
2416 	if (result == -1)
2417 		psql_error("could not start editor \"%s\"\n", editorName);
2418 	else if (result == 127)
2419 		psql_error("could not start /bin/sh\n");
2420 	free(sys);
2421 
2422 	return result == 0;
2423 }
2424 
2425 
2426 /* call this one */
2427 static bool
do_edit(const char * filename_arg,PQExpBuffer query_buf,int lineno,bool * edited)2428 do_edit(const char *filename_arg, PQExpBuffer query_buf,
2429 		int lineno, bool *edited)
2430 {
2431 	char		fnametmp[MAXPGPATH];
2432 	FILE	   *stream = NULL;
2433 	const char *fname;
2434 	bool		error = false;
2435 	int			fd;
2436 	struct stat before,
2437 				after;
2438 
2439 	if (filename_arg)
2440 		fname = filename_arg;
2441 	else
2442 	{
2443 		/* make a temp file to edit */
2444 #ifndef WIN32
2445 		const char *tmpdir = getenv("TMPDIR");
2446 
2447 		if (!tmpdir)
2448 			tmpdir = "/tmp";
2449 #else
2450 		char		tmpdir[MAXPGPATH];
2451 		int			ret;
2452 
2453 		ret = GetTempPath(MAXPGPATH, tmpdir);
2454 		if (ret == 0 || ret > MAXPGPATH)
2455 		{
2456 			psql_error("could not locate temporary directory: %s\n",
2457 					   !ret ? strerror(errno) : "");
2458 			return false;
2459 		}
2460 #endif
2461 
2462 		/*
2463 		 * No canonicalize_path() here. EDIT.EXE run from CMD.EXE prepends the
2464 		 * current directory to the supplied path unless we use only
2465 		 * backslashes, so we do that.
2466 		 */
2467 #ifndef WIN32
2468 		snprintf(fnametmp, sizeof(fnametmp), "%s%spsql.edit.%d.sql", tmpdir,
2469 				 "/", (int) getpid());
2470 #else
2471 		snprintf(fnametmp, sizeof(fnametmp), "%s%spsql.edit.%d.sql", tmpdir,
2472 			   "" /* trailing separator already present */ , (int) getpid());
2473 #endif
2474 
2475 		fname = (const char *) fnametmp;
2476 
2477 		fd = open(fname, O_WRONLY | O_CREAT | O_EXCL, 0600);
2478 		if (fd != -1)
2479 			stream = fdopen(fd, "w");
2480 
2481 		if (fd == -1 || !stream)
2482 		{
2483 			psql_error("could not open temporary file \"%s\": %s\n", fname, strerror(errno));
2484 			error = true;
2485 		}
2486 		else
2487 		{
2488 			unsigned int ql = query_buf->len;
2489 
2490 			if (ql == 0 || query_buf->data[ql - 1] != '\n')
2491 			{
2492 				appendPQExpBufferChar(query_buf, '\n');
2493 				ql++;
2494 			}
2495 
2496 			if (fwrite(query_buf->data, 1, ql, stream) != ql)
2497 			{
2498 				psql_error("%s: %s\n", fname, strerror(errno));
2499 
2500 				if (fclose(stream) != 0)
2501 					psql_error("%s: %s\n", fname, strerror(errno));
2502 
2503 				if (remove(fname) != 0)
2504 					psql_error("%s: %s\n", fname, strerror(errno));
2505 
2506 				error = true;
2507 			}
2508 			else if (fclose(stream) != 0)
2509 			{
2510 				psql_error("%s: %s\n", fname, strerror(errno));
2511 				if (remove(fname) != 0)
2512 					psql_error("%s: %s\n", fname, strerror(errno));
2513 				error = true;
2514 			}
2515 			else
2516 			{
2517 				struct utimbuf ut;
2518 
2519 				/*
2520 				 * Try to set the file modification time of the temporary file
2521 				 * a few seconds in the past.  Otherwise, the low granularity
2522 				 * (one second, or even worse on some filesystems) that we can
2523 				 * portably measure with stat(2) could lead us to not
2524 				 * recognize a modification, if the user typed very quickly.
2525 				 *
2526 				 * This is a rather unlikely race condition, so don't error
2527 				 * out if the utime(2) call fails --- that would make the cure
2528 				 * worse than the disease.
2529 				 */
2530 				ut.modtime = ut.actime = time(NULL) - 2;
2531 				(void) utime(fname, &ut);
2532 			}
2533 		}
2534 	}
2535 
2536 	if (!error && stat(fname, &before) != 0)
2537 	{
2538 		psql_error("%s: %s\n", fname, strerror(errno));
2539 		error = true;
2540 	}
2541 
2542 	/* call editor */
2543 	if (!error)
2544 		error = !editFile(fname, lineno);
2545 
2546 	if (!error && stat(fname, &after) != 0)
2547 	{
2548 		psql_error("%s: %s\n", fname, strerror(errno));
2549 		error = true;
2550 	}
2551 
2552 	/* file was edited if the size or modification time has changed */
2553 	if (!error &&
2554 		(before.st_size != after.st_size ||
2555 		 before.st_mtime != after.st_mtime))
2556 	{
2557 		stream = fopen(fname, PG_BINARY_R);
2558 		if (!stream)
2559 		{
2560 			psql_error("%s: %s\n", fname, strerror(errno));
2561 			error = true;
2562 		}
2563 		else
2564 		{
2565 			/* read file back into query_buf */
2566 			char		line[1024];
2567 
2568 			resetPQExpBuffer(query_buf);
2569 			while (fgets(line, sizeof(line), stream) != NULL)
2570 				appendPQExpBufferStr(query_buf, line);
2571 
2572 			if (ferror(stream))
2573 			{
2574 				psql_error("%s: %s\n", fname, strerror(errno));
2575 				error = true;
2576 			}
2577 			else if (edited)
2578 			{
2579 				*edited = true;
2580 			}
2581 
2582 			fclose(stream);
2583 		}
2584 	}
2585 
2586 	/* remove temp file */
2587 	if (!filename_arg)
2588 	{
2589 		if (remove(fname) == -1)
2590 		{
2591 			psql_error("%s: %s\n", fname, strerror(errno));
2592 			error = true;
2593 		}
2594 	}
2595 
2596 	return !error;
2597 }
2598 
2599 
2600 
2601 /*
2602  * process_file
2603  *
2604  * Reads commands from filename and passes them to the main processing loop.
2605  * Handler for \i and \ir, but can be used for other things as well.  Returns
2606  * MainLoop() error code.
2607  *
2608  * If use_relative_path is true and filename is not an absolute path, then open
2609  * the file from where the currently processed file (if any) is located.
2610  */
2611 int
process_file(char * filename,bool use_relative_path)2612 process_file(char *filename, bool use_relative_path)
2613 {
2614 	FILE	   *fd;
2615 	int			result;
2616 	char	   *oldfilename;
2617 	char		relpath[MAXPGPATH];
2618 
2619 	if (!filename)
2620 	{
2621 		fd = stdin;
2622 		filename = NULL;
2623 	}
2624 	else if (strcmp(filename, "-") != 0)
2625 	{
2626 		canonicalize_path(filename);
2627 
2628 		/*
2629 		 * If we were asked to resolve the pathname relative to the location
2630 		 * of the currently executing script, and there is one, and this is a
2631 		 * relative pathname, then prepend all but the last pathname component
2632 		 * of the current script to this pathname.
2633 		 */
2634 		if (use_relative_path && pset.inputfile &&
2635 			!is_absolute_path(filename) && !has_drive_prefix(filename))
2636 		{
2637 			strlcpy(relpath, pset.inputfile, sizeof(relpath));
2638 			get_parent_directory(relpath);
2639 			join_path_components(relpath, relpath, filename);
2640 			canonicalize_path(relpath);
2641 
2642 			filename = relpath;
2643 		}
2644 
2645 		fd = fopen(filename, PG_BINARY_R);
2646 
2647 		if (!fd)
2648 		{
2649 			psql_error("%s: %s\n", filename, strerror(errno));
2650 			return EXIT_FAILURE;
2651 		}
2652 	}
2653 	else
2654 	{
2655 		fd = stdin;
2656 		filename = "<stdin>";	/* for future error messages */
2657 	}
2658 
2659 	oldfilename = pset.inputfile;
2660 	pset.inputfile = filename;
2661 
2662 	result = MainLoop(fd);
2663 
2664 	if (fd != stdin)
2665 		fclose(fd);
2666 
2667 	pset.inputfile = oldfilename;
2668 	return result;
2669 }
2670 
2671 
2672 
2673 static const char *
_align2string(enum printFormat in)2674 _align2string(enum printFormat in)
2675 {
2676 	switch (in)
2677 	{
2678 		case PRINT_NOTHING:
2679 			return "nothing";
2680 			break;
2681 		case PRINT_UNALIGNED:
2682 			return "unaligned";
2683 			break;
2684 		case PRINT_ALIGNED:
2685 			return "aligned";
2686 			break;
2687 		case PRINT_WRAPPED:
2688 			return "wrapped";
2689 			break;
2690 		case PRINT_HTML:
2691 			return "html";
2692 			break;
2693 		case PRINT_ASCIIDOC:
2694 			return "asciidoc";
2695 			break;
2696 		case PRINT_LATEX:
2697 			return "latex";
2698 			break;
2699 		case PRINT_LATEX_LONGTABLE:
2700 			return "latex-longtable";
2701 			break;
2702 		case PRINT_TROFF_MS:
2703 			return "troff-ms";
2704 			break;
2705 	}
2706 	return "unknown";
2707 }
2708 
2709 /*
2710  * Parse entered Unicode linestyle.  If ok, update *linestyle and return
2711  * true, else return false.
2712  */
2713 static bool
set_unicode_line_style(const char * value,size_t vallen,unicode_linestyle * linestyle)2714 set_unicode_line_style(const char *value, size_t vallen,
2715 					   unicode_linestyle *linestyle)
2716 {
2717 	if (pg_strncasecmp("single", value, vallen) == 0)
2718 		*linestyle = UNICODE_LINESTYLE_SINGLE;
2719 	else if (pg_strncasecmp("double", value, vallen) == 0)
2720 		*linestyle = UNICODE_LINESTYLE_DOUBLE;
2721 	else
2722 		return false;
2723 	return true;
2724 }
2725 
2726 static const char *
_unicode_linestyle2string(int linestyle)2727 _unicode_linestyle2string(int linestyle)
2728 {
2729 	switch (linestyle)
2730 	{
2731 		case UNICODE_LINESTYLE_SINGLE:
2732 			return "single";
2733 			break;
2734 		case UNICODE_LINESTYLE_DOUBLE:
2735 			return "double";
2736 			break;
2737 	}
2738 	return "unknown";
2739 }
2740 
2741 /*
2742  * do_pset
2743  *
2744  */
2745 bool
do_pset(const char * param,const char * value,printQueryOpt * popt,bool quiet)2746 do_pset(const char *param, const char *value, printQueryOpt *popt, bool quiet)
2747 {
2748 	size_t		vallen = 0;
2749 
2750 	Assert(param != NULL);
2751 
2752 	if (value)
2753 		vallen = strlen(value);
2754 
2755 	/* set format */
2756 	if (strcmp(param, "format") == 0)
2757 	{
2758 		if (!value)
2759 			;
2760 		else if (pg_strncasecmp("unaligned", value, vallen) == 0)
2761 			popt->topt.format = PRINT_UNALIGNED;
2762 		else if (pg_strncasecmp("aligned", value, vallen) == 0)
2763 			popt->topt.format = PRINT_ALIGNED;
2764 		else if (pg_strncasecmp("wrapped", value, vallen) == 0)
2765 			popt->topt.format = PRINT_WRAPPED;
2766 		else if (pg_strncasecmp("html", value, vallen) == 0)
2767 			popt->topt.format = PRINT_HTML;
2768 		else if (pg_strncasecmp("asciidoc", value, vallen) == 0)
2769 			popt->topt.format = PRINT_ASCIIDOC;
2770 		else if (pg_strncasecmp("latex", value, vallen) == 0)
2771 			popt->topt.format = PRINT_LATEX;
2772 		else if (pg_strncasecmp("latex-longtable", value, vallen) == 0)
2773 			popt->topt.format = PRINT_LATEX_LONGTABLE;
2774 		else if (pg_strncasecmp("troff-ms", value, vallen) == 0)
2775 			popt->topt.format = PRINT_TROFF_MS;
2776 		else
2777 		{
2778 			psql_error("\\pset: allowed formats are unaligned, aligned, wrapped, html, asciidoc, latex, latex-longtable, troff-ms\n");
2779 			return false;
2780 		}
2781 
2782 	}
2783 
2784 	/* set table line style */
2785 	else if (strcmp(param, "linestyle") == 0)
2786 	{
2787 		if (!value)
2788 			;
2789 		else if (pg_strncasecmp("ascii", value, vallen) == 0)
2790 			popt->topt.line_style = &pg_asciiformat;
2791 		else if (pg_strncasecmp("old-ascii", value, vallen) == 0)
2792 			popt->topt.line_style = &pg_asciiformat_old;
2793 		else if (pg_strncasecmp("unicode", value, vallen) == 0)
2794 			popt->topt.line_style = &pg_utf8format;
2795 		else
2796 		{
2797 			psql_error("\\pset: allowed line styles are ascii, old-ascii, unicode\n");
2798 			return false;
2799 		}
2800 
2801 	}
2802 
2803 	/* set unicode border line style */
2804 	else if (strcmp(param, "unicode_border_linestyle") == 0)
2805 	{
2806 		if (!value)
2807 			;
2808 		else if (set_unicode_line_style(value, vallen,
2809 										&popt->topt.unicode_border_linestyle))
2810 			refresh_utf8format(&(popt->topt));
2811 		else
2812 		{
2813 			psql_error("\\pset: allowed Unicode border line styles are single, double\n");
2814 			return false;
2815 		}
2816 	}
2817 
2818 	/* set unicode column line style */
2819 	else if (strcmp(param, "unicode_column_linestyle") == 0)
2820 	{
2821 		if (!value)
2822 			;
2823 		else if (set_unicode_line_style(value, vallen,
2824 										&popt->topt.unicode_column_linestyle))
2825 			refresh_utf8format(&(popt->topt));
2826 		else
2827 		{
2828 			psql_error("\\pset: allowed Unicode column line styles are single, double\n");
2829 			return false;
2830 		}
2831 	}
2832 
2833 	/* set unicode header line style */
2834 	else if (strcmp(param, "unicode_header_linestyle") == 0)
2835 	{
2836 		if (!value)
2837 			;
2838 		else if (set_unicode_line_style(value, vallen,
2839 										&popt->topt.unicode_header_linestyle))
2840 			refresh_utf8format(&(popt->topt));
2841 		else
2842 		{
2843 			psql_error("\\pset: allowed Unicode header line styles are single, double\n");
2844 			return false;
2845 		}
2846 	}
2847 
2848 	/* set border style/width */
2849 	else if (strcmp(param, "border") == 0)
2850 	{
2851 		if (value)
2852 			popt->topt.border = atoi(value);
2853 
2854 	}
2855 
2856 	/* set expanded/vertical mode */
2857 	else if (strcmp(param, "x") == 0 ||
2858 			 strcmp(param, "expanded") == 0 ||
2859 			 strcmp(param, "vertical") == 0)
2860 	{
2861 		if (value && pg_strcasecmp(value, "auto") == 0)
2862 			popt->topt.expanded = 2;
2863 		else if (value)
2864 			popt->topt.expanded = ParseVariableBool(value, param);
2865 		else
2866 			popt->topt.expanded = !popt->topt.expanded;
2867 	}
2868 
2869 	/* locale-aware numeric output */
2870 	else if (strcmp(param, "numericlocale") == 0)
2871 	{
2872 		if (value)
2873 			popt->topt.numericLocale = ParseVariableBool(value, param);
2874 		else
2875 			popt->topt.numericLocale = !popt->topt.numericLocale;
2876 	}
2877 
2878 	/* null display */
2879 	else if (strcmp(param, "null") == 0)
2880 	{
2881 		if (value)
2882 		{
2883 			free(popt->nullPrint);
2884 			popt->nullPrint = pg_strdup(value);
2885 		}
2886 	}
2887 
2888 	/* field separator for unaligned text */
2889 	else if (strcmp(param, "fieldsep") == 0)
2890 	{
2891 		if (value)
2892 		{
2893 			free(popt->topt.fieldSep.separator);
2894 			popt->topt.fieldSep.separator = pg_strdup(value);
2895 			popt->topt.fieldSep.separator_zero = false;
2896 		}
2897 	}
2898 
2899 	else if (strcmp(param, "fieldsep_zero") == 0)
2900 	{
2901 		free(popt->topt.fieldSep.separator);
2902 		popt->topt.fieldSep.separator = NULL;
2903 		popt->topt.fieldSep.separator_zero = true;
2904 	}
2905 
2906 	/* record separator for unaligned text */
2907 	else if (strcmp(param, "recordsep") == 0)
2908 	{
2909 		if (value)
2910 		{
2911 			free(popt->topt.recordSep.separator);
2912 			popt->topt.recordSep.separator = pg_strdup(value);
2913 			popt->topt.recordSep.separator_zero = false;
2914 		}
2915 	}
2916 
2917 	else if (strcmp(param, "recordsep_zero") == 0)
2918 	{
2919 		free(popt->topt.recordSep.separator);
2920 		popt->topt.recordSep.separator = NULL;
2921 		popt->topt.recordSep.separator_zero = true;
2922 	}
2923 
2924 	/* toggle between full and tuples-only format */
2925 	else if (strcmp(param, "t") == 0 || strcmp(param, "tuples_only") == 0)
2926 	{
2927 		if (value)
2928 			popt->topt.tuples_only = ParseVariableBool(value, param);
2929 		else
2930 			popt->topt.tuples_only = !popt->topt.tuples_only;
2931 	}
2932 
2933 	/* set title override */
2934 	else if (strcmp(param, "C") == 0 || strcmp(param, "title") == 0)
2935 	{
2936 		free(popt->title);
2937 		if (!value)
2938 			popt->title = NULL;
2939 		else
2940 			popt->title = pg_strdup(value);
2941 	}
2942 
2943 	/* set HTML table tag options */
2944 	else if (strcmp(param, "T") == 0 || strcmp(param, "tableattr") == 0)
2945 	{
2946 		free(popt->topt.tableAttr);
2947 		if (!value)
2948 			popt->topt.tableAttr = NULL;
2949 		else
2950 			popt->topt.tableAttr = pg_strdup(value);
2951 	}
2952 
2953 	/* toggle use of pager */
2954 	else if (strcmp(param, "pager") == 0)
2955 	{
2956 		if (value && pg_strcasecmp(value, "always") == 0)
2957 			popt->topt.pager = 2;
2958 		else if (value)
2959 		{
2960 			if (ParseVariableBool(value, param))
2961 				popt->topt.pager = 1;
2962 			else
2963 				popt->topt.pager = 0;
2964 		}
2965 		else if (popt->topt.pager == 1)
2966 			popt->topt.pager = 0;
2967 		else
2968 			popt->topt.pager = 1;
2969 	}
2970 
2971 	/* set minimum lines for pager use */
2972 	else if (strcmp(param, "pager_min_lines") == 0)
2973 	{
2974 		if (value)
2975 			popt->topt.pager_min_lines = atoi(value);
2976 	}
2977 
2978 	/* disable "(x rows)" footer */
2979 	else if (strcmp(param, "footer") == 0)
2980 	{
2981 		if (value)
2982 			popt->topt.default_footer = ParseVariableBool(value, param);
2983 		else
2984 			popt->topt.default_footer = !popt->topt.default_footer;
2985 	}
2986 
2987 	/* set border style/width */
2988 	else if (strcmp(param, "columns") == 0)
2989 	{
2990 		if (value)
2991 			popt->topt.columns = atoi(value);
2992 	}
2993 	else
2994 	{
2995 		psql_error("\\pset: unknown option: %s\n", param);
2996 		return false;
2997 	}
2998 
2999 	if (!quiet)
3000 		printPsetInfo(param, &pset.popt);
3001 
3002 	return true;
3003 }
3004 
3005 
3006 static bool
printPsetInfo(const char * param,struct printQueryOpt * popt)3007 printPsetInfo(const char *param, struct printQueryOpt *popt)
3008 {
3009 	Assert(param != NULL);
3010 
3011 	/* show border style/width */
3012 	if (strcmp(param, "border") == 0)
3013 		printf(_("Border style is %d.\n"), popt->topt.border);
3014 
3015 	/* show the target width for the wrapped format */
3016 	else if (strcmp(param, "columns") == 0)
3017 	{
3018 		if (!popt->topt.columns)
3019 			printf(_("Target width is unset.\n"));
3020 		else
3021 			printf(_("Target width is %d.\n"), popt->topt.columns);
3022 	}
3023 
3024 	/* show expanded/vertical mode */
3025 	else if (strcmp(param, "x") == 0 || strcmp(param, "expanded") == 0 || strcmp(param, "vertical") == 0)
3026 	{
3027 		if (popt->topt.expanded == 1)
3028 			printf(_("Expanded display is on.\n"));
3029 		else if (popt->topt.expanded == 2)
3030 			printf(_("Expanded display is used automatically.\n"));
3031 		else
3032 			printf(_("Expanded display is off.\n"));
3033 	}
3034 
3035 	/* show field separator for unaligned text */
3036 	else if (strcmp(param, "fieldsep") == 0)
3037 	{
3038 		if (popt->topt.fieldSep.separator_zero)
3039 			printf(_("Field separator is zero byte.\n"));
3040 		else
3041 			printf(_("Field separator is \"%s\".\n"),
3042 				   popt->topt.fieldSep.separator);
3043 	}
3044 
3045 	else if (strcmp(param, "fieldsep_zero") == 0)
3046 	{
3047 		printf(_("Field separator is zero byte.\n"));
3048 	}
3049 
3050 	/* show disable "(x rows)" footer */
3051 	else if (strcmp(param, "footer") == 0)
3052 	{
3053 		if (popt->topt.default_footer)
3054 			printf(_("Default footer is on.\n"));
3055 		else
3056 			printf(_("Default footer is off.\n"));
3057 	}
3058 
3059 	/* show format */
3060 	else if (strcmp(param, "format") == 0)
3061 	{
3062 		printf(_("Output format is %s.\n"), _align2string(popt->topt.format));
3063 	}
3064 
3065 	/* show table line style */
3066 	else if (strcmp(param, "linestyle") == 0)
3067 	{
3068 		printf(_("Line style is %s.\n"),
3069 			   get_line_style(&popt->topt)->name);
3070 	}
3071 
3072 	/* show null display */
3073 	else if (strcmp(param, "null") == 0)
3074 	{
3075 		printf(_("Null display is \"%s\".\n"),
3076 			   popt->nullPrint ? popt->nullPrint : "");
3077 	}
3078 
3079 	/* show locale-aware numeric output */
3080 	else if (strcmp(param, "numericlocale") == 0)
3081 	{
3082 		if (popt->topt.numericLocale)
3083 			printf(_("Locale-adjusted numeric output is on.\n"));
3084 		else
3085 			printf(_("Locale-adjusted numeric output is off.\n"));
3086 	}
3087 
3088 	/* show toggle use of pager */
3089 	else if (strcmp(param, "pager") == 0)
3090 	{
3091 		if (popt->topt.pager == 1)
3092 			printf(_("Pager is used for long output.\n"));
3093 		else if (popt->topt.pager == 2)
3094 			printf(_("Pager is always used.\n"));
3095 		else
3096 			printf(_("Pager usage is off.\n"));
3097 	}
3098 
3099 	/* show minimum lines for pager use */
3100 	else if (strcmp(param, "pager_min_lines") == 0)
3101 	{
3102 		printf(ngettext("Pager won't be used for less than %d line.\n",
3103 						"Pager won't be used for less than %d lines.\n",
3104 						popt->topt.pager_min_lines),
3105 			   popt->topt.pager_min_lines);
3106 	}
3107 
3108 	/* show record separator for unaligned text */
3109 	else if (strcmp(param, "recordsep") == 0)
3110 	{
3111 		if (popt->topt.recordSep.separator_zero)
3112 			printf(_("Record separator is zero byte.\n"));
3113 		else if (strcmp(popt->topt.recordSep.separator, "\n") == 0)
3114 			printf(_("Record separator is <newline>.\n"));
3115 		else
3116 			printf(_("Record separator is \"%s\".\n"),
3117 				   popt->topt.recordSep.separator);
3118 	}
3119 
3120 	else if (strcmp(param, "recordsep_zero") == 0)
3121 	{
3122 		printf(_("Record separator is zero byte.\n"));
3123 	}
3124 
3125 	/* show HTML table tag options */
3126 	else if (strcmp(param, "T") == 0 || strcmp(param, "tableattr") == 0)
3127 	{
3128 		if (popt->topt.tableAttr)
3129 			printf(_("Table attributes are \"%s\".\n"),
3130 				   popt->topt.tableAttr);
3131 		else
3132 			printf(_("Table attributes unset.\n"));
3133 	}
3134 
3135 	/* show title override */
3136 	else if (strcmp(param, "C") == 0 || strcmp(param, "title") == 0)
3137 	{
3138 		if (popt->title)
3139 			printf(_("Title is \"%s\".\n"), popt->title);
3140 		else
3141 			printf(_("Title is unset.\n"));
3142 	}
3143 
3144 	/* show toggle between full and tuples-only format */
3145 	else if (strcmp(param, "t") == 0 || strcmp(param, "tuples_only") == 0)
3146 	{
3147 		if (popt->topt.tuples_only)
3148 			printf(_("Tuples only is on.\n"));
3149 		else
3150 			printf(_("Tuples only is off.\n"));
3151 	}
3152 
3153 	/* Unicode style formatting */
3154 	else if (strcmp(param, "unicode_border_linestyle") == 0)
3155 	{
3156 		printf(_("Unicode border line style is \"%s\".\n"),
3157 			 _unicode_linestyle2string(popt->topt.unicode_border_linestyle));
3158 	}
3159 
3160 	else if (strcmp(param, "unicode_column_linestyle") == 0)
3161 	{
3162 		printf(_("Unicode column line style is \"%s\".\n"),
3163 			 _unicode_linestyle2string(popt->topt.unicode_column_linestyle));
3164 	}
3165 
3166 	else if (strcmp(param, "unicode_header_linestyle") == 0)
3167 	{
3168 		printf(_("Unicode header line style is \"%s\".\n"),
3169 			 _unicode_linestyle2string(popt->topt.unicode_header_linestyle));
3170 	}
3171 
3172 	else
3173 	{
3174 		psql_error("\\pset: unknown option: %s\n", param);
3175 		return false;
3176 	}
3177 
3178 	return true;
3179 }
3180 
3181 
3182 static const char *
pset_bool_string(bool val)3183 pset_bool_string(bool val)
3184 {
3185 	return val ? "on" : "off";
3186 }
3187 
3188 
3189 static char *
pset_quoted_string(const char * str)3190 pset_quoted_string(const char *str)
3191 {
3192 	char	   *ret = pg_malloc(strlen(str) * 2 + 3);
3193 	char	   *r = ret;
3194 
3195 	*r++ = '\'';
3196 
3197 	for (; *str; str++)
3198 	{
3199 		if (*str == '\n')
3200 		{
3201 			*r++ = '\\';
3202 			*r++ = 'n';
3203 		}
3204 		else if (*str == '\'')
3205 		{
3206 			*r++ = '\\';
3207 			*r++ = '\'';
3208 		}
3209 		else
3210 			*r++ = *str;
3211 	}
3212 
3213 	*r++ = '\'';
3214 	*r = '\0';
3215 
3216 	return ret;
3217 }
3218 
3219 
3220 /*
3221  * Return a malloc'ed string for the \pset value.
3222  *
3223  * Note that for some string parameters, print.c distinguishes between unset
3224  * and empty string, but for others it doesn't.  This function should produce
3225  * output that produces the correct setting when fed back into \pset.
3226  */
3227 static char *
pset_value_string(const char * param,struct printQueryOpt * popt)3228 pset_value_string(const char *param, struct printQueryOpt *popt)
3229 {
3230 	Assert(param != NULL);
3231 
3232 	if (strcmp(param, "border") == 0)
3233 		return psprintf("%d", popt->topt.border);
3234 	else if (strcmp(param, "columns") == 0)
3235 		return psprintf("%d", popt->topt.columns);
3236 	else if (strcmp(param, "expanded") == 0)
3237 		return pstrdup(popt->topt.expanded == 2
3238 					   ? "auto"
3239 					   : pset_bool_string(popt->topt.expanded));
3240 	else if (strcmp(param, "fieldsep") == 0)
3241 		return pset_quoted_string(popt->topt.fieldSep.separator
3242 								  ? popt->topt.fieldSep.separator
3243 								  : "");
3244 	else if (strcmp(param, "fieldsep_zero") == 0)
3245 		return pstrdup(pset_bool_string(popt->topt.fieldSep.separator_zero));
3246 	else if (strcmp(param, "footer") == 0)
3247 		return pstrdup(pset_bool_string(popt->topt.default_footer));
3248 	else if (strcmp(param, "format") == 0)
3249 		return psprintf("%s", _align2string(popt->topt.format));
3250 	else if (strcmp(param, "linestyle") == 0)
3251 		return psprintf("%s", get_line_style(&popt->topt)->name);
3252 	else if (strcmp(param, "null") == 0)
3253 		return pset_quoted_string(popt->nullPrint
3254 								  ? popt->nullPrint
3255 								  : "");
3256 	else if (strcmp(param, "numericlocale") == 0)
3257 		return pstrdup(pset_bool_string(popt->topt.numericLocale));
3258 	else if (strcmp(param, "pager") == 0)
3259 		return psprintf("%d", popt->topt.pager);
3260 	else if (strcmp(param, "pager_min_lines") == 0)
3261 		return psprintf("%d", popt->topt.pager_min_lines);
3262 	else if (strcmp(param, "recordsep") == 0)
3263 		return pset_quoted_string(popt->topt.recordSep.separator
3264 								  ? popt->topt.recordSep.separator
3265 								  : "");
3266 	else if (strcmp(param, "recordsep_zero") == 0)
3267 		return pstrdup(pset_bool_string(popt->topt.recordSep.separator_zero));
3268 	else if (strcmp(param, "tableattr") == 0)
3269 		return popt->topt.tableAttr ? pset_quoted_string(popt->topt.tableAttr) : pstrdup("");
3270 	else if (strcmp(param, "title") == 0)
3271 		return popt->title ? pset_quoted_string(popt->title) : pstrdup("");
3272 	else if (strcmp(param, "tuples_only") == 0)
3273 		return pstrdup(pset_bool_string(popt->topt.tuples_only));
3274 	else if (strcmp(param, "unicode_border_linestyle") == 0)
3275 		return pstrdup(_unicode_linestyle2string(popt->topt.unicode_border_linestyle));
3276 	else if (strcmp(param, "unicode_column_linestyle") == 0)
3277 		return pstrdup(_unicode_linestyle2string(popt->topt.unicode_column_linestyle));
3278 	else if (strcmp(param, "unicode_header_linestyle") == 0)
3279 		return pstrdup(_unicode_linestyle2string(popt->topt.unicode_header_linestyle));
3280 	else
3281 		return pstrdup("ERROR");
3282 }
3283 
3284 
3285 
3286 #ifndef WIN32
3287 #define DEFAULT_SHELL "/bin/sh"
3288 #else
3289 /*
3290  *	CMD.EXE is in different places in different Win32 releases so we
3291  *	have to rely on the path to find it.
3292  */
3293 #define DEFAULT_SHELL "cmd.exe"
3294 #endif
3295 
3296 static bool
do_shell(const char * command)3297 do_shell(const char *command)
3298 {
3299 	int			result;
3300 
3301 	if (!command)
3302 	{
3303 		char	   *sys;
3304 		const char *shellName;
3305 
3306 		shellName = getenv("SHELL");
3307 #ifdef WIN32
3308 		if (shellName == NULL)
3309 			shellName = getenv("COMSPEC");
3310 #endif
3311 		if (shellName == NULL)
3312 			shellName = DEFAULT_SHELL;
3313 
3314 		/* See EDITOR handling comment for an explanation */
3315 #ifndef WIN32
3316 		sys = psprintf("exec %s", shellName);
3317 #else
3318 		sys = psprintf("\"%s\"", shellName);
3319 #endif
3320 		result = system(sys);
3321 		free(sys);
3322 	}
3323 	else
3324 		result = system(command);
3325 
3326 	if (result == 127 || result == -1)
3327 	{
3328 		psql_error("\\!: failed\n");
3329 		return false;
3330 	}
3331 	return true;
3332 }
3333 
3334 /*
3335  * do_watch -- handler for \watch
3336  *
3337  * We break this out of exec_command to avoid having to plaster "volatile"
3338  * onto a bunch of exec_command's variables to silence stupider compilers.
3339  */
3340 static bool
do_watch(PQExpBuffer query_buf,double sleep)3341 do_watch(PQExpBuffer query_buf, double sleep)
3342 {
3343 	long		sleep_ms = (long) (sleep * 1000);
3344 	printQueryOpt myopt = pset.popt;
3345 	const char *strftime_fmt;
3346 	const char *user_title;
3347 	char	   *title;
3348 	int			title_len;
3349 	int			res = 0;
3350 
3351 	if (!query_buf || query_buf->len <= 0)
3352 	{
3353 		psql_error(_("\\watch cannot be used with an empty query\n"));
3354 		return false;
3355 	}
3356 
3357 	/*
3358 	 * Choose format for timestamps.  We might eventually make this a \pset
3359 	 * option.  In the meantime, using a variable for the format suppresses
3360 	 * overly-anal-retentive gcc warnings about %c being Y2K sensitive.
3361 	 */
3362 	strftime_fmt = "%c";
3363 
3364 	/*
3365 	 * Set up rendering options, in particular, disable the pager, because
3366 	 * nobody wants to be prompted while watching the output of 'watch'.
3367 	 */
3368 	myopt.topt.pager = 0;
3369 
3370 	/*
3371 	 * If there's a title in the user configuration, make sure we have room
3372 	 * for it in the title buffer.  Allow 128 bytes for the timestamp plus 128
3373 	 * bytes for the rest.
3374 	 */
3375 	user_title = myopt.title;
3376 	title_len = (user_title ? strlen(user_title) : 0) + 256;
3377 	title = pg_malloc(title_len);
3378 
3379 	for (;;)
3380 	{
3381 		time_t		timer;
3382 		char		timebuf[128];
3383 		long		i;
3384 
3385 		/*
3386 		 * Prepare title for output.  Note that we intentionally include a
3387 		 * newline at the end of the title; this is somewhat historical but it
3388 		 * makes for reasonably nicely formatted output in simple cases.
3389 		 */
3390 		timer = time(NULL);
3391 		strftime(timebuf, sizeof(timebuf), strftime_fmt, localtime(&timer));
3392 
3393 		if (user_title)
3394 			snprintf(title, title_len, _("%s\t%s (every %gs)\n"),
3395 					 user_title, timebuf, sleep);
3396 		else
3397 			snprintf(title, title_len, _("%s (every %gs)\n"),
3398 					 timebuf, sleep);
3399 		myopt.title = title;
3400 
3401 		/* Run the query and print out the results */
3402 		res = PSQLexecWatch(query_buf->data, &myopt);
3403 
3404 		/*
3405 		 * PSQLexecWatch handles the case where we can no longer repeat the
3406 		 * query, and returns 0 or -1.
3407 		 */
3408 		if (res <= 0)
3409 			break;
3410 
3411 		/*
3412 		 * Set up cancellation of 'watch' via SIGINT.  We redo this each time
3413 		 * through the loop since it's conceivable something inside
3414 		 * PSQLexecWatch could change sigint_interrupt_jmp.
3415 		 */
3416 		if (sigsetjmp(sigint_interrupt_jmp, 1) != 0)
3417 			break;
3418 
3419 		/*
3420 		 * Enable 'watch' cancellations and wait a while before running the
3421 		 * query again.  Break the sleep into short intervals (at most 1s)
3422 		 * since pg_usleep isn't interruptible on some platforms.
3423 		 */
3424 		sigint_interrupt_enabled = true;
3425 		i = sleep_ms;
3426 		while (i > 0)
3427 		{
3428 			long		s = Min(i, 1000L);
3429 
3430 			pg_usleep(s * 1000L);
3431 			if (cancel_pressed)
3432 				break;
3433 			i -= s;
3434 		}
3435 		sigint_interrupt_enabled = false;
3436 	}
3437 
3438 	pg_free(title);
3439 	return (res >= 0);
3440 }
3441 
3442 /*
3443  * a little code borrowed from PSQLexec() to manage ECHO_HIDDEN output.
3444  * returns true unless we have ECHO_HIDDEN_NOEXEC.
3445  */
3446 static bool
echo_hidden_command(const char * query)3447 echo_hidden_command(const char *query)
3448 {
3449 	if (pset.echo_hidden != PSQL_ECHO_HIDDEN_OFF)
3450 	{
3451 		printf(_("********* QUERY **********\n"
3452 				 "%s\n"
3453 				 "**************************\n\n"), query);
3454 		fflush(stdout);
3455 		if (pset.logfile)
3456 		{
3457 			fprintf(pset.logfile,
3458 					_("********* QUERY **********\n"
3459 					  "%s\n"
3460 					  "**************************\n\n"), query);
3461 			fflush(pset.logfile);
3462 		}
3463 
3464 		if (pset.echo_hidden == PSQL_ECHO_HIDDEN_NOEXEC)
3465 			return false;
3466 	}
3467 	return true;
3468 }
3469 
3470 /*
3471  * Look up the object identified by obj_type and desc.  If successful,
3472  * store its OID in *obj_oid and return TRUE, else return FALSE.
3473  *
3474  * Note that we'll fail if the object doesn't exist OR if there are multiple
3475  * matching candidates OR if there's something syntactically wrong with the
3476  * object description; unfortunately it can be hard to tell the difference.
3477  */
3478 static bool
lookup_object_oid(EditableObjectType obj_type,const char * desc,Oid * obj_oid)3479 lookup_object_oid(EditableObjectType obj_type, const char *desc,
3480 				  Oid *obj_oid)
3481 {
3482 	bool		result = true;
3483 	PQExpBuffer query = createPQExpBuffer();
3484 	PGresult   *res;
3485 
3486 	switch (obj_type)
3487 	{
3488 		case EditableFunction:
3489 
3490 			/*
3491 			 * We have a function description, e.g. "x" or "x(int)".  Issue a
3492 			 * query to retrieve the function's OID using a cast to regproc or
3493 			 * regprocedure (as appropriate).
3494 			 */
3495 			appendPQExpBufferStr(query, "SELECT ");
3496 			appendStringLiteralConn(query, desc, pset.db);
3497 			appendPQExpBuffer(query, "::pg_catalog.%s::pg_catalog.oid",
3498 							  strchr(desc, '(') ? "regprocedure" : "regproc");
3499 			break;
3500 
3501 		case EditableView:
3502 
3503 			/*
3504 			 * Convert view name (possibly schema-qualified) to OID.  Note:
3505 			 * this code doesn't check if the relation is actually a view.
3506 			 * We'll detect that in get_create_object_cmd().
3507 			 */
3508 			appendPQExpBufferStr(query, "SELECT ");
3509 			appendStringLiteralConn(query, desc, pset.db);
3510 			appendPQExpBuffer(query, "::pg_catalog.regclass::pg_catalog.oid");
3511 			break;
3512 	}
3513 
3514 	if (!echo_hidden_command(query->data))
3515 	{
3516 		destroyPQExpBuffer(query);
3517 		return false;
3518 	}
3519 	res = PQexec(pset.db, query->data);
3520 	if (PQresultStatus(res) == PGRES_TUPLES_OK && PQntuples(res) == 1)
3521 		*obj_oid = atooid(PQgetvalue(res, 0, 0));
3522 	else
3523 	{
3524 		minimal_error_message(res);
3525 		result = false;
3526 	}
3527 
3528 	PQclear(res);
3529 	destroyPQExpBuffer(query);
3530 
3531 	return result;
3532 }
3533 
3534 /*
3535  * Construct a "CREATE OR REPLACE ..." command that describes the specified
3536  * database object.  If successful, the result is stored in buf.
3537  */
3538 static bool
get_create_object_cmd(EditableObjectType obj_type,Oid oid,PQExpBuffer buf)3539 get_create_object_cmd(EditableObjectType obj_type, Oid oid,
3540 					  PQExpBuffer buf)
3541 {
3542 	bool		result = true;
3543 	PQExpBuffer query = createPQExpBuffer();
3544 	PGresult   *res;
3545 
3546 	switch (obj_type)
3547 	{
3548 		case EditableFunction:
3549 			printfPQExpBuffer(query,
3550 							  "SELECT pg_catalog.pg_get_functiondef(%u)",
3551 							  oid);
3552 			break;
3553 
3554 		case EditableView:
3555 
3556 			/*
3557 			 * pg_get_viewdef() just prints the query, so we must prepend
3558 			 * CREATE for ourselves.  We must fully qualify the view name to
3559 			 * ensure the right view gets replaced.  Also, check relation kind
3560 			 * to be sure it's a view.
3561 			 *
3562 			 * Starting with 9.2, views may have reloptions (security_barrier)
3563 			 * and from 9.4 onwards they may also have WITH [LOCAL|CASCADED]
3564 			 * CHECK OPTION.  These are not part of the view definition
3565 			 * returned by pg_get_viewdef() and so need to be retrieved
3566 			 * separately.  Materialized views (introduced in 9.3) may have
3567 			 * arbitrary storage parameter reloptions.
3568 			 */
3569 			if (pset.sversion >= 90400)
3570 			{
3571 				printfPQExpBuffer(query,
3572 								  "SELECT nspname, relname, relkind, "
3573 								  "pg_catalog.pg_get_viewdef(c.oid, true), "
3574 								  "array_remove(array_remove(c.reloptions,'check_option=local'),'check_option=cascaded') AS reloptions, "
3575 								  "CASE WHEN 'check_option=local' = ANY (c.reloptions) THEN 'LOCAL'::text "
3576 								  "WHEN 'check_option=cascaded' = ANY (c.reloptions) THEN 'CASCADED'::text ELSE NULL END AS checkoption "
3577 								  "FROM pg_catalog.pg_class c "
3578 								  "LEFT JOIN pg_catalog.pg_namespace n "
3579 								"ON c.relnamespace = n.oid WHERE c.oid = %u",
3580 								  oid);
3581 			}
3582 			else if (pset.sversion >= 90200)
3583 			{
3584 				printfPQExpBuffer(query,
3585 								  "SELECT nspname, relname, relkind, "
3586 								  "pg_catalog.pg_get_viewdef(c.oid, true), "
3587 								  "c.reloptions AS reloptions, "
3588 								  "NULL AS checkoption "
3589 								  "FROM pg_catalog.pg_class c "
3590 								  "LEFT JOIN pg_catalog.pg_namespace n "
3591 								"ON c.relnamespace = n.oid WHERE c.oid = %u",
3592 								  oid);
3593 			}
3594 			else
3595 			{
3596 				printfPQExpBuffer(query,
3597 								  "SELECT nspname, relname, relkind, "
3598 								  "pg_catalog.pg_get_viewdef(c.oid, true), "
3599 								  "NULL AS reloptions, "
3600 								  "NULL AS checkoption "
3601 								  "FROM pg_catalog.pg_class c "
3602 								  "LEFT JOIN pg_catalog.pg_namespace n "
3603 								"ON c.relnamespace = n.oid WHERE c.oid = %u",
3604 								  oid);
3605 			}
3606 			break;
3607 	}
3608 
3609 	if (!echo_hidden_command(query->data))
3610 	{
3611 		destroyPQExpBuffer(query);
3612 		return false;
3613 	}
3614 	res = PQexec(pset.db, query->data);
3615 	if (PQresultStatus(res) == PGRES_TUPLES_OK && PQntuples(res) == 1)
3616 	{
3617 		resetPQExpBuffer(buf);
3618 		switch (obj_type)
3619 		{
3620 			case EditableFunction:
3621 				appendPQExpBufferStr(buf, PQgetvalue(res, 0, 0));
3622 				break;
3623 
3624 			case EditableView:
3625 				{
3626 					char	   *nspname = PQgetvalue(res, 0, 0);
3627 					char	   *relname = PQgetvalue(res, 0, 1);
3628 					char	   *relkind = PQgetvalue(res, 0, 2);
3629 					char	   *viewdef = PQgetvalue(res, 0, 3);
3630 					char	   *reloptions = PQgetvalue(res, 0, 4);
3631 					char	   *checkoption = PQgetvalue(res, 0, 5);
3632 
3633 					/*
3634 					 * If the backend ever supports CREATE OR REPLACE
3635 					 * MATERIALIZED VIEW, allow that here; but as of today it
3636 					 * does not, so editing a matview definition in this way
3637 					 * is impossible.
3638 					 */
3639 					switch (relkind[0])
3640 					{
3641 #ifdef NOT_USED
3642 						case 'm':
3643 							appendPQExpBufferStr(buf, "CREATE OR REPLACE MATERIALIZED VIEW ");
3644 							break;
3645 #endif
3646 						case 'v':
3647 							appendPQExpBufferStr(buf, "CREATE OR REPLACE VIEW ");
3648 							break;
3649 						default:
3650 							psql_error("\"%s.%s\" is not a view\n",
3651 									   nspname, relname);
3652 							result = false;
3653 							break;
3654 					}
3655 					appendPQExpBuffer(buf, "%s.", fmtId(nspname));
3656 					appendPQExpBufferStr(buf, fmtId(relname));
3657 
3658 					/* reloptions, if not an empty array "{}" */
3659 					if (reloptions != NULL && strlen(reloptions) > 2)
3660 					{
3661 						appendPQExpBufferStr(buf, "\n WITH (");
3662 						if (!appendReloptionsArray(buf, reloptions, "",
3663 												   pset.encoding,
3664 												   standard_strings()))
3665 						{
3666 							psql_error("could not parse reloptions array\n");
3667 							result = false;
3668 						}
3669 						appendPQExpBufferStr(buf, ")");
3670 					}
3671 
3672 					/* View definition from pg_get_viewdef (a SELECT query) */
3673 					appendPQExpBuffer(buf, " AS\n%s", viewdef);
3674 
3675 					/* Get rid of the semicolon that pg_get_viewdef appends */
3676 					if (buf->len > 0 && buf->data[buf->len - 1] == ';')
3677 						buf->data[--(buf->len)] = '\0';
3678 
3679 					/* WITH [LOCAL|CASCADED] CHECK OPTION */
3680 					if (checkoption && checkoption[0] != '\0')
3681 						appendPQExpBuffer(buf, "\n WITH %s CHECK OPTION",
3682 										  checkoption);
3683 				}
3684 				break;
3685 		}
3686 		/* Make sure result ends with a newline */
3687 		if (buf->len > 0 && buf->data[buf->len - 1] != '\n')
3688 			appendPQExpBufferChar(buf, '\n');
3689 	}
3690 	else
3691 	{
3692 		minimal_error_message(res);
3693 		result = false;
3694 	}
3695 
3696 	PQclear(res);
3697 	destroyPQExpBuffer(query);
3698 
3699 	return result;
3700 }
3701 
3702 /*
3703  * If the given argument of \ef or \ev ends with a line number, delete the line
3704  * number from the argument string and return it as an integer.  (We need
3705  * this kluge because we're too lazy to parse \ef's function or \ev's view
3706  * argument carefully --- we just slop it up in OT_WHOLE_LINE mode.)
3707  *
3708  * Returns -1 if no line number is present, 0 on error, or a positive value
3709  * on success.
3710  */
3711 static int
strip_lineno_from_objdesc(char * obj)3712 strip_lineno_from_objdesc(char *obj)
3713 {
3714 	char	   *c;
3715 	int			lineno;
3716 
3717 	if (!obj || obj[0] == '\0')
3718 		return -1;
3719 
3720 	c = obj + strlen(obj) - 1;
3721 
3722 	/*
3723 	 * This business of parsing backwards is dangerous as can be in a
3724 	 * multibyte environment: there is no reason to believe that we are
3725 	 * looking at the first byte of a character, nor are we necessarily
3726 	 * working in a "safe" encoding.  Fortunately the bitpatterns we are
3727 	 * looking for are unlikely to occur as non-first bytes, but beware of
3728 	 * trying to expand the set of cases that can be recognized.  We must
3729 	 * guard the <ctype.h> macros by using isascii() first, too.
3730 	 */
3731 
3732 	/* skip trailing whitespace */
3733 	while (c > obj && isascii((unsigned char) *c) && isspace((unsigned char) *c))
3734 		c--;
3735 
3736 	/* must have a digit as last non-space char */
3737 	if (c == obj || !isascii((unsigned char) *c) || !isdigit((unsigned char) *c))
3738 		return -1;
3739 
3740 	/* find start of digit string */
3741 	while (c > obj && isascii((unsigned char) *c) && isdigit((unsigned char) *c))
3742 		c--;
3743 
3744 	/* digits must be separated from object name by space or closing paren */
3745 	/* notice also that we are not allowing an empty object name ... */
3746 	if (c == obj || !isascii((unsigned char) *c) ||
3747 		!(isspace((unsigned char) *c) || *c == ')'))
3748 		return -1;
3749 
3750 	/* parse digit string */
3751 	c++;
3752 	lineno = atoi(c);
3753 	if (lineno < 1)
3754 	{
3755 		psql_error("invalid line number: %s\n", c);
3756 		return 0;
3757 	}
3758 
3759 	/* strip digit string from object name */
3760 	*c = '\0';
3761 
3762 	return lineno;
3763 }
3764 
3765 /*
3766  * Count number of lines in the buffer.
3767  * This is used to test if pager is needed or not.
3768  */
3769 static int
count_lines_in_buf(PQExpBuffer buf)3770 count_lines_in_buf(PQExpBuffer buf)
3771 {
3772 	int			lineno = 0;
3773 	const char *lines = buf->data;
3774 
3775 	while (*lines != '\0')
3776 	{
3777 		lineno++;
3778 		/* find start of next line */
3779 		lines = strchr(lines, '\n');
3780 		if (!lines)
3781 			break;
3782 		lines++;
3783 	}
3784 
3785 	return lineno;
3786 }
3787 
3788 /*
3789  * Write text at *lines to output with line numbers.
3790  *
3791  * If header_keyword isn't NULL, then line 1 should be the first line beginning
3792  * with header_keyword; lines before that are unnumbered.
3793  *
3794  * Caution: this scribbles on *lines.
3795  */
3796 static void
print_with_linenumbers(FILE * output,char * lines,const char * header_keyword)3797 print_with_linenumbers(FILE *output, char *lines,
3798 					   const char *header_keyword)
3799 {
3800 	bool		in_header = (header_keyword != NULL);
3801 	size_t		header_sz = in_header ? strlen(header_keyword) : 0;
3802 	int			lineno = 0;
3803 
3804 	while (*lines != '\0')
3805 	{
3806 		char	   *eol;
3807 
3808 		if (in_header && strncmp(lines, header_keyword, header_sz) == 0)
3809 			in_header = false;
3810 
3811 		/* increment lineno only for body's lines */
3812 		if (!in_header)
3813 			lineno++;
3814 
3815 		/* find and mark end of current line */
3816 		eol = strchr(lines, '\n');
3817 		if (eol != NULL)
3818 			*eol = '\0';
3819 
3820 		/* show current line as appropriate */
3821 		if (in_header)
3822 			fprintf(output, "        %s\n", lines);
3823 		else
3824 			fprintf(output, "%-7d %s\n", lineno, lines);
3825 
3826 		/* advance to next line, if any */
3827 		if (eol == NULL)
3828 			break;
3829 		lines = ++eol;
3830 	}
3831 }
3832 
3833 /*
3834  * Report just the primary error; this is to avoid cluttering the output
3835  * with, for instance, a redisplay of the internally generated query
3836  */
3837 static void
minimal_error_message(PGresult * res)3838 minimal_error_message(PGresult *res)
3839 {
3840 	PQExpBuffer msg;
3841 	const char *fld;
3842 
3843 	msg = createPQExpBuffer();
3844 
3845 	fld = PQresultErrorField(res, PG_DIAG_SEVERITY);
3846 	if (fld)
3847 		printfPQExpBuffer(msg, "%s:  ", fld);
3848 	else
3849 		printfPQExpBuffer(msg, "ERROR:  ");
3850 	fld = PQresultErrorField(res, PG_DIAG_MESSAGE_PRIMARY);
3851 	if (fld)
3852 		appendPQExpBufferStr(msg, fld);
3853 	else
3854 		appendPQExpBufferStr(msg, "(not available)");
3855 	appendPQExpBufferStr(msg, "\n");
3856 
3857 	psql_error("%s", msg->data);
3858 
3859 	destroyPQExpBuffer(msg);
3860 }
3861