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, "e, 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, "ed, 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