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