]> granicus.if.org Git - postgresql/blob - src/bin/psql/command.c
Teach psql to display the comments on conversions and domains.
[postgresql] / src / bin / psql / command.c
1 /*
2  * psql - the PostgreSQL interactive terminal
3  *
4  * Copyright (c) 2000-2011, 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 #ifdef HAVE_PWD_H
17 #include <pwd.h>
18 #endif
19 #ifndef WIN32
20 #include <sys/types.h>                  /* for umask() */
21 #include <sys/stat.h>                   /* for stat() */
22 #include <fcntl.h>                              /* open() flags */
23 #include <unistd.h>                             /* for geteuid(), getpid(), stat() */
24 #else
25 #include <win32.h>
26 #include <io.h>
27 #include <fcntl.h>
28 #include <direct.h>
29 #include <sys/types.h>                  /* for umask() */
30 #include <sys/stat.h>                   /* for stat() */
31 #endif
32 #ifdef USE_SSL
33 #include <openssl/ssl.h>
34 #endif
35
36 #include "portability/instr_time.h"
37
38 #include "libpq-fe.h"
39 #include "pqexpbuffer.h"
40 #include "dumputils.h"
41
42 #include "common.h"
43 #include "copy.h"
44 #include "describe.h"
45 #include "help.h"
46 #include "input.h"
47 #include "large_obj.h"
48 #include "mainloop.h"
49 #include "print.h"
50 #include "psqlscan.h"
51 #include "settings.h"
52 #include "variables.h"
53
54
55 /* functions for use in this file */
56 static backslashResult exec_command(const char *cmd,
57                          PsqlScanState scan_state,
58                          PQExpBuffer query_buf);
59 static bool do_edit(const char *filename_arg, PQExpBuffer query_buf,
60                 int lineno, bool *edited);
61 static bool do_connect(char *dbname, char *user, char *host, char *port);
62 static bool do_shell(const char *command);
63 static bool lookup_function_oid(PGconn *conn, const char *desc, Oid *foid);
64 static bool get_create_function_cmd(PGconn *conn, Oid oid, PQExpBuffer buf);
65 static int      strip_lineno_from_funcdesc(char *func);
66 static void minimal_error_message(PGresult *res);
67
68 static void printSSLInfo(void);
69
70 #ifdef WIN32
71 static void checkWin32Codepage(void);
72 #endif
73
74
75
76 /*----------
77  * HandleSlashCmds:
78  *
79  * Handles all the different commands that start with '\'.
80  * Ordinarily called by MainLoop().
81  *
82  * scan_state is a lexer working state that is set to continue scanning
83  * just after the '\'.  The lexer is advanced past the command and all
84  * arguments on return.
85  *
86  * 'query_buf' contains the query-so-far, which may be modified by
87  * execution of the backslash command (for example, \r clears it).
88  * query_buf can be NULL if there is no query so far.
89  *
90  * Returns a status code indicating what action is desired, see command.h.
91  *----------
92  */
93
94 backslashResult
95 HandleSlashCmds(PsqlScanState scan_state,
96                                 PQExpBuffer query_buf)
97 {
98         backslashResult status = PSQL_CMD_SKIP_LINE;
99         char       *cmd;
100         char       *arg;
101
102         psql_assert(scan_state);
103
104         /* Parse off the command name */
105         cmd = psql_scan_slash_command(scan_state);
106
107         /* And try to execute it */
108         status = exec_command(cmd, scan_state, query_buf);
109
110         if (status == PSQL_CMD_UNKNOWN)
111         {
112                 if (pset.cur_cmd_interactive)
113                         fprintf(stderr, _("Invalid command \\%s. Try \\? for help.\n"), cmd);
114                 else
115                         psql_error("invalid command \\%s\n", cmd);
116                 status = PSQL_CMD_ERROR;
117         }
118
119         if (status != PSQL_CMD_ERROR)
120         {
121                 /* eat any remaining arguments after a valid command */
122                 /* note we suppress evaluation of backticks here */
123                 while ((arg = psql_scan_slash_option(scan_state,
124                                                                                          OT_VERBATIM, NULL, false)))
125                 {
126                         psql_error("\\%s: extra argument \"%s\" ignored\n", cmd, arg);
127                         free(arg);
128                 }
129         }
130         else
131         {
132                 /* silently throw away rest of line after an erroneous command */
133                 while ((arg = psql_scan_slash_option(scan_state,
134                                                                                          OT_WHOLE_LINE, NULL, false)))
135                         free(arg);
136         }
137
138         /* if there is a trailing \\, swallow it */
139         psql_scan_slash_command_end(scan_state);
140
141         free(cmd);
142
143         /* some commands write to queryFout, so make sure output is sent */
144         fflush(pset.queryFout);
145
146         return status;
147 }
148
149 /*
150  * Read and interpret an argument to the \connect slash command.
151  */
152 static char *
153 read_connect_arg(PsqlScanState scan_state)
154 {
155         char       *result;
156         char            quote;
157
158         /*
159          * Ideally we should treat the arguments as SQL identifiers.  But for
160          * backwards compatibility with 7.2 and older pg_dump files, we have to
161          * take unquoted arguments verbatim (don't downcase them). For now,
162          * double-quoted arguments may be stripped of double quotes (as if SQL
163          * identifiers).  By 7.4 or so, pg_dump files can be expected to
164          * double-quote all mixed-case \connect arguments, and then we can get rid
165          * of OT_SQLIDHACK.
166          */
167         result = psql_scan_slash_option(scan_state, OT_SQLIDHACK, &quote, true);
168
169         if (!result)
170                 return NULL;
171
172         if (quote)
173                 return result;
174
175         if (*result == '\0' || strcmp(result, "-") == 0)
176                 return NULL;
177
178         return result;
179 }
180
181
182 /*
183  * Subroutine to actually try to execute a backslash command.
184  */
185 static backslashResult
186 exec_command(const char *cmd,
187                          PsqlScanState scan_state,
188                          PQExpBuffer query_buf)
189 {
190         bool            success = true; /* indicate here if the command ran ok or
191                                                                  * failed */
192         backslashResult status = PSQL_CMD_SKIP_LINE;
193
194         /*
195          * \a -- toggle field alignment This makes little sense but we keep it
196          * around.
197          */
198         if (strcmp(cmd, "a") == 0)
199         {
200                 if (pset.popt.topt.format != PRINT_ALIGNED)
201                         success = do_pset("format", "aligned", &pset.popt, pset.quiet);
202                 else
203                         success = do_pset("format", "unaligned", &pset.popt, pset.quiet);
204         }
205
206         /* \C -- override table title (formerly change HTML caption) */
207         else if (strcmp(cmd, "C") == 0)
208         {
209                 char       *opt = psql_scan_slash_option(scan_state,
210                                                                                                  OT_NORMAL, NULL, true);
211
212                 success = do_pset("title", opt, &pset.popt, pset.quiet);
213                 free(opt);
214         }
215
216         /*
217          * \c or \connect -- connect to database using the specified parameters.
218          *
219          * \c dbname user host port
220          *
221          * If any of these parameters are omitted or specified as '-', the current
222          * value of the parameter will be used instead. If the parameter has no
223          * current value, the default value for that parameter will be used. Some
224          * examples:
225          *
226          * \c - - hst           Connect to current database on current port of host
227          * "hst" as current user. \c - usr - prt   Connect to current database on
228          * "prt" port of current host as user "usr". \c dbs                       Connect to
229          * "dbs" database on current port of current host as current user.
230          */
231         else if (strcmp(cmd, "c") == 0 || strcmp(cmd, "connect") == 0)
232         {
233                 char       *opt1,
234                                    *opt2,
235                                    *opt3,
236                                    *opt4;
237
238                 opt1 = read_connect_arg(scan_state);
239                 opt2 = read_connect_arg(scan_state);
240                 opt3 = read_connect_arg(scan_state);
241                 opt4 = read_connect_arg(scan_state);
242
243                 success = do_connect(opt1, opt2, opt3, opt4);
244
245                 free(opt1);
246                 free(opt2);
247                 free(opt3);
248                 free(opt4);
249         }
250
251         /* \cd */
252         else if (strcmp(cmd, "cd") == 0)
253         {
254                 char       *opt = psql_scan_slash_option(scan_state,
255                                                                                                  OT_NORMAL, NULL, true);
256                 char       *dir;
257
258                 if (opt)
259                         dir = opt;
260                 else
261                 {
262 #ifndef WIN32
263                         struct passwd *pw;
264
265                         pw = getpwuid(geteuid());
266                         if (!pw)
267                         {
268                                 psql_error("could not get home directory: %s\n", strerror(errno));
269                                 exit(EXIT_FAILURE);
270                         }
271                         dir = pw->pw_dir;
272 #else                                                   /* WIN32 */
273
274                         /*
275                          * On Windows, 'cd' without arguments prints the current
276                          * directory, so if someone wants to code this here instead...
277                          */
278                         dir = "/";
279 #endif   /* WIN32 */
280                 }
281
282                 if (chdir(dir) == -1)
283                 {
284                         psql_error("\\%s: could not change directory to \"%s\": %s\n",
285                                            cmd, dir, strerror(errno));
286                         success = false;
287                 }
288
289                 if (pset.dirname)
290                         free(pset.dirname);
291                 pset.dirname = pg_strdup(dir);
292                 canonicalize_path(pset.dirname);
293
294                 if (opt)
295                         free(opt);
296         }
297
298         /* \conninfo -- display information about the current connection */
299         else if (strcmp(cmd, "conninfo") == 0)
300         {
301                 char       *db = PQdb(pset.db);
302                 char       *host = PQhost(pset.db);
303
304                 if (db == NULL)
305                         printf(_("You are currently not connected to a database.\n"));
306                 else
307                 {
308                         if (host == NULL)
309                                 host = DEFAULT_PGSOCKET_DIR;
310                         /* If the host is an absolute path, the connection is via socket */
311                         if (is_absolute_path(host))
312                                 printf(_("You are connected to database \"%s\" as user \"%s\" via socket in \"%s\" at port \"%s\".\n"),
313                                            db, PQuser(pset.db), host, PQport(pset.db));
314                         else
315                                 printf(_("You are connected to database \"%s\" as user \"%s\" on host \"%s\" at port \"%s\".\n"),
316                                            db, PQuser(pset.db), host, PQport(pset.db));
317                 }
318         }
319
320         /* \copy */
321         else if (pg_strcasecmp(cmd, "copy") == 0)
322         {
323                 /* Default fetch-it-all-and-print mode */
324                 instr_time      before,
325                                         after;
326
327                 char       *opt = psql_scan_slash_option(scan_state,
328                                                                                                  OT_WHOLE_LINE, NULL, false);
329
330                 if (pset.timing)
331                         INSTR_TIME_SET_CURRENT(before);
332
333                 success = do_copy(opt);
334
335                 if (pset.timing && success)
336                 {
337                         INSTR_TIME_SET_CURRENT(after);
338                         INSTR_TIME_SUBTRACT(after, before);
339                         printf(_("Time: %.3f ms\n"), INSTR_TIME_GET_MILLISEC(after));
340                 }
341
342                 free(opt);
343         }
344
345         /* \copyright */
346         else if (strcmp(cmd, "copyright") == 0)
347                 print_copyright();
348
349         /* \d* commands */
350         else if (cmd[0] == 'd')
351         {
352                 char       *pattern;
353                 bool            show_verbose,
354                                         show_system;
355
356                 /* We don't do SQLID reduction on the pattern yet */
357                 pattern = psql_scan_slash_option(scan_state,
358                                                                                  OT_NORMAL, NULL, true);
359
360                 show_verbose = strchr(cmd, '+') ? true : false;
361                 show_system = strchr(cmd, 'S') ? true : false;
362
363                 switch (cmd[1])
364                 {
365                         case '\0':
366                         case '+':
367                         case 'S':
368                                 if (pattern)
369                                         success = describeTableDetails(pattern, show_verbose, show_system);
370                                 else
371                                         /* standard listing of interesting things */
372                                         success = listTables("tvsE", NULL, show_verbose, show_system);
373                                 break;
374                         case 'a':
375                                 success = describeAggregates(pattern, show_verbose, show_system);
376                                 break;
377                         case 'b':
378                                 success = describeTablespaces(pattern, show_verbose);
379                                 break;
380                         case 'c':
381                                 success = listConversions(pattern, show_verbose, show_system);
382                                 break;
383                         case 'C':
384                                 success = listCasts(pattern, show_verbose);
385                                 break;
386                         case 'd':
387                                 if (strncmp(cmd, "ddp", 3) == 0)
388                                         success = listDefaultACLs(pattern);
389                                 else
390                                         success = objectDescription(pattern, show_system);
391                                 break;
392                         case 'D':
393                                 success = listDomains(pattern, show_verbose, show_system);
394                                 break;
395                         case 'f':                       /* function subsystem */
396                                 switch (cmd[2])
397                                 {
398                                         case '\0':
399                                         case '+':
400                                         case 'S':
401                                         case 'a':
402                                         case 'n':
403                                         case 't':
404                                         case 'w':
405                                                 success = describeFunctions(&cmd[2], pattern, show_verbose, show_system);
406                                                 break;
407                                         default:
408                                                 status = PSQL_CMD_UNKNOWN;
409                                                 break;
410                                 }
411                                 break;
412                         case 'g':
413                                 /* no longer distinct from \du */
414                                 success = describeRoles(pattern, show_verbose);
415                                 break;
416                         case 'l':
417                                 success = do_lo_list();
418                                 break;
419                         case 'L':
420                                 success = listLanguages(pattern, show_verbose, show_system);
421                                 break;
422                         case 'n':
423                                 success = listSchemas(pattern, show_verbose, show_system);
424                                 break;
425                         case 'o':
426                                 success = describeOperators(pattern, show_system);
427                                 break;
428                         case 'O':
429                                 success = listCollations(pattern, show_verbose, show_system);
430                                 break;
431                         case 'p':
432                                 success = permissionsList(pattern);
433                                 break;
434                         case 'T':
435                                 success = describeTypes(pattern, show_verbose, show_system);
436                                 break;
437                         case 't':
438                         case 'v':
439                         case 'i':
440                         case 's':
441                         case 'E':
442                                 success = listTables(&cmd[1], pattern, show_verbose, show_system);
443                                 break;
444                         case 'r':
445                                 if (cmd[2] == 'd' && cmd[3] == 's')
446                                 {
447                                         char       *pattern2 = NULL;
448
449                                         if (pattern)
450                                                 pattern2 = psql_scan_slash_option(scan_state,
451                                                                                                           OT_NORMAL, NULL, true);
452                                         success = listDbRoleSettings(pattern, pattern2);
453                                 }
454                                 else
455                                         success = PSQL_CMD_UNKNOWN;
456                                 break;
457                         case 'u':
458                                 success = describeRoles(pattern, show_verbose);
459                                 break;
460                         case 'F':                       /* text search subsystem */
461                                 switch (cmd[2])
462                                 {
463                                         case '\0':
464                                         case '+':
465                                                 success = listTSConfigs(pattern, show_verbose);
466                                                 break;
467                                         case 'p':
468                                                 success = listTSParsers(pattern, show_verbose);
469                                                 break;
470                                         case 'd':
471                                                 success = listTSDictionaries(pattern, show_verbose);
472                                                 break;
473                                         case 't':
474                                                 success = listTSTemplates(pattern, show_verbose);
475                                                 break;
476                                         default:
477                                                 status = PSQL_CMD_UNKNOWN;
478                                                 break;
479                                 }
480                                 break;
481                         case 'e':                       /* SQL/MED subsystem */
482                                 switch (cmd[2])
483                                 {
484                                         case 's':
485                                                 success = listForeignServers(pattern, show_verbose);
486                                                 break;
487                                         case 'u':
488                                                 success = listUserMappings(pattern, show_verbose);
489                                                 break;
490                                         case 'w':
491                                                 success = listForeignDataWrappers(pattern, show_verbose);
492                                                 break;
493                                         case 't':
494                                                 success = listForeignTables(pattern, show_verbose);
495                                                 break;
496                                         default:
497                                                 status = PSQL_CMD_UNKNOWN;
498                                                 break;
499                                 }
500                                 break;
501                         case 'x':                       /* Extensions */
502                                 if (show_verbose)
503                                         success = listExtensionContents(pattern);
504                                 else
505                                         success = listExtensions(pattern);
506                                 break;
507                         default:
508                                 status = PSQL_CMD_UNKNOWN;
509                 }
510
511                 if (pattern)
512                         free(pattern);
513         }
514
515
516         /*
517          * \e or \edit -- edit the current query buffer, or edit a file and make
518          * it the query buffer
519          */
520         else if (strcmp(cmd, "e") == 0 || strcmp(cmd, "edit") == 0)
521         {
522                 if (!query_buf)
523                 {
524                         psql_error("no query buffer\n");
525                         status = PSQL_CMD_ERROR;
526                 }
527                 else
528                 {
529                         char       *fname;
530                         char       *ln = NULL;
531                         int                     lineno = -1;
532
533                         fname = psql_scan_slash_option(scan_state,
534                                                                                    OT_NORMAL, NULL, true);
535                         if (fname)
536                         {
537                                 /* try to get separate lineno arg */
538                                 ln = psql_scan_slash_option(scan_state,
539                                                                                         OT_NORMAL, NULL, true);
540                                 if (ln == NULL)
541                                 {
542                                         /* only one arg; maybe it is lineno not fname */
543                                         if (fname[0] &&
544                                                 strspn(fname, "0123456789") == strlen(fname))
545                                         {
546                                                 /* all digits, so assume it is lineno */
547                                                 ln = fname;
548                                                 fname = NULL;
549                                         }
550                                 }
551                         }
552                         if (ln)
553                         {
554                                 lineno = atoi(ln);
555                                 if (lineno < 1)
556                                 {
557                                         psql_error("invalid line number: %s\n", ln);
558                                         status = PSQL_CMD_ERROR;
559                                 }
560                         }
561                         if (status != PSQL_CMD_ERROR)
562                         {
563                                 expand_tilde(&fname);
564                                 if (fname)
565                                         canonicalize_path(fname);
566                                 if (do_edit(fname, query_buf, lineno, NULL))
567                                         status = PSQL_CMD_NEWEDIT;
568                                 else
569                                         status = PSQL_CMD_ERROR;
570                         }
571                         if (fname)
572                                 free(fname);
573                         if (ln)
574                                 free(ln);
575                 }
576         }
577
578         /*
579          * \ef -- edit the named function, or present a blank CREATE FUNCTION
580          * template if no argument is given
581          */
582         else if (strcmp(cmd, "ef") == 0)
583         {
584                 int                     lineno = -1;
585
586                 if (!query_buf)
587                 {
588                         psql_error("no query buffer\n");
589                         status = PSQL_CMD_ERROR;
590                 }
591                 else
592                 {
593                         char       *func;
594                         Oid                     foid = InvalidOid;
595
596                         func = psql_scan_slash_option(scan_state,
597                                                                                   OT_WHOLE_LINE, NULL, true);
598                         lineno = strip_lineno_from_funcdesc(func);
599                         if (lineno == 0)
600                         {
601                                 /* error already reported */
602                                 status = PSQL_CMD_ERROR;
603                         }
604                         else if (!func)
605                         {
606                                 /* set up an empty command to fill in */
607                                 printfPQExpBuffer(query_buf,
608                                                                   "CREATE FUNCTION ( )\n"
609                                                                   " RETURNS \n"
610                                                                   " LANGUAGE \n"
611                                                                   " -- common options:  IMMUTABLE  STABLE  STRICT  SECURITY DEFINER\n"
612                                                                   "AS $function$\n"
613                                                                   "\n$function$\n");
614                         }
615                         else if (!lookup_function_oid(pset.db, func, &foid))
616                         {
617                                 /* error already reported */
618                                 status = PSQL_CMD_ERROR;
619                         }
620                         else if (!get_create_function_cmd(pset.db, foid, query_buf))
621                         {
622                                 /* error already reported */
623                                 status = PSQL_CMD_ERROR;
624                         }
625                         else if (lineno > 0)
626                         {
627                                 /*
628                                  * lineno "1" should correspond to the first line of the
629                                  * function body.  We expect that pg_get_functiondef() will
630                                  * emit that on a line beginning with "AS ", and that there
631                                  * can be no such line before the real start of the function
632                                  * body.  Increment lineno by the number of lines before that
633                                  * line, so that it becomes relative to the first line of the
634                                  * function definition.
635                                  */
636                                 const char *lines = query_buf->data;
637
638                                 while (*lines != '\0')
639                                 {
640                                         if (strncmp(lines, "AS ", 3) == 0)
641                                                 break;
642                                         lineno++;
643                                         /* find start of next line */
644                                         lines = strchr(lines, '\n');
645                                         if (!lines)
646                                                 break;
647                                         lines++;
648                                 }
649                         }
650
651                         if (func)
652                                 free(func);
653                 }
654
655                 if (status != PSQL_CMD_ERROR)
656                 {
657                         bool            edited = false;
658
659                         if (!do_edit(NULL, query_buf, lineno, &edited))
660                                 status = PSQL_CMD_ERROR;
661                         else if (!edited)
662                                 puts(_("No changes"));
663                         else
664                                 status = PSQL_CMD_NEWEDIT;
665                 }
666         }
667
668         /* \echo and \qecho */
669         else if (strcmp(cmd, "echo") == 0 || strcmp(cmd, "qecho") == 0)
670         {
671                 char       *value;
672                 char            quoted;
673                 bool            no_newline = false;
674                 bool            first = true;
675                 FILE       *fout;
676
677                 if (strcmp(cmd, "qecho") == 0)
678                         fout = pset.queryFout;
679                 else
680                         fout = stdout;
681
682                 while ((value = psql_scan_slash_option(scan_state,
683                                                                                            OT_NORMAL, &quoted, false)))
684                 {
685                         if (!quoted && strcmp(value, "-n") == 0)
686                                 no_newline = true;
687                         else
688                         {
689                                 if (first)
690                                         first = false;
691                                 else
692                                         fputc(' ', fout);
693                                 fputs(value, fout);
694                         }
695                         free(value);
696                 }
697                 if (!no_newline)
698                         fputs("\n", fout);
699         }
700
701         /* \encoding -- set/show client side encoding */
702         else if (strcmp(cmd, "encoding") == 0)
703         {
704                 char       *encoding = psql_scan_slash_option(scan_state,
705                                                                                                           OT_NORMAL, NULL, false);
706
707                 if (!encoding)
708                 {
709                         /* show encoding */
710                         puts(pg_encoding_to_char(pset.encoding));
711                 }
712                 else
713                 {
714                         /* set encoding */
715                         if (PQsetClientEncoding(pset.db, encoding) == -1)
716                                 psql_error("%s: invalid encoding name or conversion procedure not found\n", encoding);
717                         else
718                         {
719                                 /* save encoding info into psql internal data */
720                                 pset.encoding = PQclientEncoding(pset.db);
721                                 pset.popt.topt.encoding = pset.encoding;
722                                 SetVariable(pset.vars, "ENCODING",
723                                                         pg_encoding_to_char(pset.encoding));
724                         }
725                         free(encoding);
726                 }
727         }
728
729         /* \f -- change field separator */
730         else if (strcmp(cmd, "f") == 0)
731         {
732                 char       *fname = psql_scan_slash_option(scan_state,
733                                                                                                    OT_NORMAL, NULL, false);
734
735                 success = do_pset("fieldsep", fname, &pset.popt, pset.quiet);
736                 free(fname);
737         }
738
739         /* \g means send query */
740         else if (strcmp(cmd, "g") == 0)
741         {
742                 char       *fname = psql_scan_slash_option(scan_state,
743                                                                                                    OT_FILEPIPE, NULL, false);
744
745                 if (!fname)
746                         pset.gfname = NULL;
747                 else
748                 {
749                         expand_tilde(&fname);
750                         pset.gfname = pg_strdup(fname);
751                 }
752                 free(fname);
753                 status = PSQL_CMD_SEND;
754         }
755
756         /* help */
757         else if (strcmp(cmd, "h") == 0 || strcmp(cmd, "help") == 0)
758         {
759                 char       *opt = psql_scan_slash_option(scan_state,
760                                                                                                  OT_WHOLE_LINE, NULL, false);
761                 size_t          len;
762
763                 /* strip any trailing spaces and semicolons */
764                 if (opt)
765                 {
766                         len = strlen(opt);
767                         while (len > 0 &&
768                                    (isspace((unsigned char) opt[len - 1])
769                                         || opt[len - 1] == ';'))
770                                 opt[--len] = '\0';
771                 }
772
773                 helpSQL(opt, pset.popt.topt.pager);
774                 free(opt);
775         }
776
777         /* HTML mode */
778         else if (strcmp(cmd, "H") == 0 || strcmp(cmd, "html") == 0)
779         {
780                 if (pset.popt.topt.format != PRINT_HTML)
781                         success = do_pset("format", "html", &pset.popt, pset.quiet);
782                 else
783                         success = do_pset("format", "aligned", &pset.popt, pset.quiet);
784         }
785
786
787         /* \i and \ir include files */
788         else if (strcmp(cmd, "i") == 0 || strcmp(cmd, "include") == 0
789                         || strcmp(cmd, "ir") == 0 || strcmp(cmd, "include_relative") == 0)
790         {
791                 char       *fname = psql_scan_slash_option(scan_state,
792                                                                                                    OT_NORMAL, NULL, true);
793
794                 if (!fname)
795                 {
796                         psql_error("\\%s: missing required argument\n", cmd);
797                         success = false;
798                 }
799                 else
800                 {
801                         bool    include_relative;
802
803                         include_relative = (strcmp(cmd, "ir") == 0
804                                                                 || strcmp(cmd, "include_relative") == 0);
805                         expand_tilde(&fname);
806                         success = (process_file(fname, false, include_relative) == EXIT_SUCCESS);
807                         free(fname);
808                 }
809         }
810
811         /* \l is list databases */
812         else if (strcmp(cmd, "l") == 0 || strcmp(cmd, "list") == 0)
813                 success = listAllDbs(false);
814         else if (strcmp(cmd, "l+") == 0 || strcmp(cmd, "list+") == 0)
815                 success = listAllDbs(true);
816
817         /*
818          * large object things
819          */
820         else if (strncmp(cmd, "lo_", 3) == 0)
821         {
822                 char       *opt1,
823                                    *opt2;
824
825                 opt1 = psql_scan_slash_option(scan_state,
826                                                                           OT_NORMAL, NULL, true);
827                 opt2 = psql_scan_slash_option(scan_state,
828                                                                           OT_NORMAL, NULL, true);
829
830                 if (strcmp(cmd + 3, "export") == 0)
831                 {
832                         if (!opt2)
833                         {
834                                 psql_error("\\%s: missing required argument\n", cmd);
835                                 success = false;
836                         }
837                         else
838                         {
839                                 expand_tilde(&opt2);
840                                 success = do_lo_export(opt1, opt2);
841                         }
842                 }
843
844                 else if (strcmp(cmd + 3, "import") == 0)
845                 {
846                         if (!opt1)
847                         {
848                                 psql_error("\\%s: missing required argument\n", cmd);
849                                 success = false;
850                         }
851                         else
852                         {
853                                 expand_tilde(&opt1);
854                                 success = do_lo_import(opt1, opt2);
855                         }
856                 }
857
858                 else if (strcmp(cmd + 3, "list") == 0)
859                         success = do_lo_list();
860
861                 else if (strcmp(cmd + 3, "unlink") == 0)
862                 {
863                         if (!opt1)
864                         {
865                                 psql_error("\\%s: missing required argument\n", cmd);
866                                 success = false;
867                         }
868                         else
869                                 success = do_lo_unlink(opt1);
870                 }
871
872                 else
873                         status = PSQL_CMD_UNKNOWN;
874
875                 free(opt1);
876                 free(opt2);
877         }
878
879
880         /* \o -- set query output */
881         else if (strcmp(cmd, "o") == 0 || strcmp(cmd, "out") == 0)
882         {
883                 char       *fname = psql_scan_slash_option(scan_state,
884                                                                                                    OT_FILEPIPE, NULL, true);
885
886                 expand_tilde(&fname);
887                 success = setQFout(fname);
888                 free(fname);
889         }
890
891         /* \p prints the current query buffer */
892         else if (strcmp(cmd, "p") == 0 || strcmp(cmd, "print") == 0)
893         {
894                 if (query_buf && query_buf->len > 0)
895                         puts(query_buf->data);
896                 else if (!pset.quiet)
897                         puts(_("Query buffer is empty."));
898                 fflush(stdout);
899         }
900
901         /* \password -- set user password */
902         else if (strcmp(cmd, "password") == 0)
903         {
904                 char       *pw1;
905                 char       *pw2;
906
907                 pw1 = simple_prompt("Enter new password: ", 100, false);
908                 pw2 = simple_prompt("Enter it again: ", 100, false);
909
910                 if (strcmp(pw1, pw2) != 0)
911                 {
912                         fprintf(stderr, _("Passwords didn't match.\n"));
913                         success = false;
914                 }
915                 else
916                 {
917                         char       *opt0 = psql_scan_slash_option(scan_state, OT_SQLID, NULL, true);
918                         char       *user;
919                         char       *encrypted_password;
920
921                         if (opt0)
922                                 user = opt0;
923                         else
924                                 user = PQuser(pset.db);
925
926                         encrypted_password = PQencryptPassword(pw1, user);
927
928                         if (!encrypted_password)
929                         {
930                                 fprintf(stderr, _("Password encryption failed.\n"));
931                                 success = false;
932                         }
933                         else
934                         {
935                                 PQExpBufferData buf;
936                                 PGresult   *res;
937
938                                 initPQExpBuffer(&buf);
939                                 printfPQExpBuffer(&buf, "ALTER USER %s PASSWORD ",
940                                                                   fmtId(user));
941                                 appendStringLiteralConn(&buf, encrypted_password, pset.db);
942                                 res = PSQLexec(buf.data, false);
943                                 termPQExpBuffer(&buf);
944                                 if (!res)
945                                         success = false;
946                                 else
947                                         PQclear(res);
948                                 PQfreemem(encrypted_password);
949                         }
950                 }
951
952                 free(pw1);
953                 free(pw2);
954         }
955
956         /* \prompt -- prompt and set variable */
957         else if (strcmp(cmd, "prompt") == 0)
958         {
959                 char       *opt,
960                                    *prompt_text = NULL;
961                 char       *arg1,
962                                    *arg2;
963
964                 arg1 = psql_scan_slash_option(scan_state, OT_NORMAL, NULL, false);
965                 arg2 = psql_scan_slash_option(scan_state, OT_NORMAL, NULL, false);
966
967                 if (!arg1)
968                 {
969                         psql_error("\\%s: missing required argument\n", cmd);
970                         success = false;
971                 }
972                 else
973                 {
974                         char       *result;
975
976                         if (arg2)
977                         {
978                                 prompt_text = arg1;
979                                 opt = arg2;
980                         }
981                         else
982                                 opt = arg1;
983
984                         if (!pset.inputfile)
985                                 result = simple_prompt(prompt_text, 4096, true);
986                         else
987                         {
988                                 if (prompt_text)
989                                 {
990                                         fputs(prompt_text, stdout);
991                                         fflush(stdout);
992                                 }
993                                 result = gets_fromFile(stdin);
994                         }
995
996                         if (!SetVariable(pset.vars, opt, result))
997                         {
998                                 psql_error("\\%s: error\n", cmd);
999                                 success = false;
1000                         }
1001
1002                         free(result);
1003                         if (prompt_text)
1004                                 free(prompt_text);
1005                         free(opt);
1006                 }
1007         }
1008
1009         /* \pset -- set printing parameters */
1010         else if (strcmp(cmd, "pset") == 0)
1011         {
1012                 char       *opt0 = psql_scan_slash_option(scan_state,
1013                                                                                                   OT_NORMAL, NULL, false);
1014                 char       *opt1 = psql_scan_slash_option(scan_state,
1015                                                                                                   OT_NORMAL, NULL, false);
1016
1017                 if (!opt0)
1018                 {
1019                         psql_error("\\%s: missing required argument\n", cmd);
1020                         success = false;
1021                 }
1022                 else
1023                         success = do_pset(opt0, opt1, &pset.popt, pset.quiet);
1024
1025                 free(opt0);
1026                 free(opt1);
1027         }
1028
1029         /* \q or \quit */
1030         else if (strcmp(cmd, "q") == 0 || strcmp(cmd, "quit") == 0)
1031                 status = PSQL_CMD_TERMINATE;
1032
1033         /* reset(clear) the buffer */
1034         else if (strcmp(cmd, "r") == 0 || strcmp(cmd, "reset") == 0)
1035         {
1036                 resetPQExpBuffer(query_buf);
1037                 psql_scan_reset(scan_state);
1038                 if (!pset.quiet)
1039                         puts(_("Query buffer reset (cleared)."));
1040         }
1041
1042         /* \s save history in a file or show it on the screen */
1043         else if (strcmp(cmd, "s") == 0)
1044         {
1045                 char       *fname = psql_scan_slash_option(scan_state,
1046                                                                                                    OT_NORMAL, NULL, true);
1047
1048                 expand_tilde(&fname);
1049                 /* This scrolls off the screen when using /dev/tty */
1050                 success = saveHistory(fname ? fname : DEVTTY, -1, false, false);
1051                 if (success && !pset.quiet && fname)
1052                         printf(gettext("Wrote history to file \"%s/%s\".\n"),
1053                                    pset.dirname ? pset.dirname : ".", fname);
1054                 if (!fname)
1055                         putchar('\n');
1056                 free(fname);
1057         }
1058
1059         /* \set -- generalized set variable/option command */
1060         else if (strcmp(cmd, "set") == 0)
1061         {
1062                 char       *opt0 = psql_scan_slash_option(scan_state,
1063                                                                                                   OT_NORMAL, NULL, false);
1064
1065                 if (!opt0)
1066                 {
1067                         /* list all variables */
1068                         PrintVariables(pset.vars);
1069                         success = true;
1070                 }
1071                 else
1072                 {
1073                         /*
1074                          * Set variable to the concatenation of the arguments.
1075                          */
1076                         char       *newval;
1077                         char       *opt;
1078
1079                         opt = psql_scan_slash_option(scan_state,
1080                                                                                  OT_NORMAL, NULL, false);
1081                         newval = pg_strdup(opt ? opt : "");
1082                         free(opt);
1083
1084                         while ((opt = psql_scan_slash_option(scan_state,
1085                                                                                                  OT_NORMAL, NULL, false)))
1086                         {
1087                                 newval = realloc(newval, strlen(newval) + strlen(opt) + 1);
1088                                 if (!newval)
1089                                 {
1090                                         psql_error("out of memory\n");
1091                                         exit(EXIT_FAILURE);
1092                                 }
1093                                 strcat(newval, opt);
1094                                 free(opt);
1095                         }
1096
1097                         if (!SetVariable(pset.vars, opt0, newval))
1098                         {
1099                                 psql_error("\\%s: error\n", cmd);
1100                                 success = false;
1101                         }
1102                         free(newval);
1103                 }
1104                 free(opt0);
1105         }
1106
1107         /* \sf -- show a function's source code */
1108         else if (strcmp(cmd, "sf") == 0 || strcmp(cmd, "sf+") == 0)
1109         {
1110                 bool            show_linenumbers = (strcmp(cmd, "sf+") == 0);
1111                 PQExpBuffer func_buf;
1112                 char       *func;
1113                 Oid                     foid = InvalidOid;
1114
1115                 func_buf = createPQExpBuffer();
1116                 func = psql_scan_slash_option(scan_state,
1117                                                                           OT_WHOLE_LINE, NULL, true);
1118                 if (!func)
1119                 {
1120                         psql_error("function name is required\n");
1121                         status = PSQL_CMD_ERROR;
1122                 }
1123                 else if (!lookup_function_oid(pset.db, func, &foid))
1124                 {
1125                         /* error already reported */
1126                         status = PSQL_CMD_ERROR;
1127                 }
1128                 else if (!get_create_function_cmd(pset.db, foid, func_buf))
1129                 {
1130                         /* error already reported */
1131                         status = PSQL_CMD_ERROR;
1132                 }
1133                 else
1134                 {
1135                         FILE       *output;
1136                         bool            is_pager;
1137
1138                         /* Select output stream: stdout, pager, or file */
1139                         if (pset.queryFout == stdout)
1140                         {
1141                                 /* count lines in function to see if pager is needed */
1142                                 int                     lineno = 0;
1143                                 const char *lines = func_buf->data;
1144
1145                                 while (*lines != '\0')
1146                                 {
1147                                         lineno++;
1148                                         /* find start of next line */
1149                                         lines = strchr(lines, '\n');
1150                                         if (!lines)
1151                                                 break;
1152                                         lines++;
1153                                 }
1154
1155                                 output = PageOutput(lineno, pset.popt.topt.pager);
1156                                 is_pager = true;
1157                         }
1158                         else
1159                         {
1160                                 /* use previously set output file, without pager */
1161                                 output = pset.queryFout;
1162                                 is_pager = false;
1163                         }
1164
1165                         if (show_linenumbers)
1166                         {
1167                                 bool            in_header = true;
1168                                 int                     lineno = 0;
1169                                 char       *lines = func_buf->data;
1170
1171                                 /*
1172                                  * lineno "1" should correspond to the first line of the
1173                                  * function body.  We expect that pg_get_functiondef() will
1174                                  * emit that on a line beginning with "AS ", and that there
1175                                  * can be no such line before the real start of the function
1176                                  * body.
1177                                  *
1178                                  * Note that this loop scribbles on func_buf.
1179                                  */
1180                                 while (*lines != '\0')
1181                                 {
1182                                         char       *eol;
1183
1184                                         if (in_header && strncmp(lines, "AS ", 3) == 0)
1185                                                 in_header = false;
1186                                         /* increment lineno only for body's lines */
1187                                         if (!in_header)
1188                                                 lineno++;
1189
1190                                         /* find and mark end of current line */
1191                                         eol = strchr(lines, '\n');
1192                                         if (eol != NULL)
1193                                                 *eol = '\0';
1194
1195                                         /* show current line as appropriate */
1196                                         if (in_header)
1197                                                 fprintf(output, "        %s\n", lines);
1198                                         else
1199                                                 fprintf(output, "%-7d %s\n", lineno, lines);
1200
1201                                         /* advance to next line, if any */
1202                                         if (eol == NULL)
1203                                                 break;
1204                                         lines = ++eol;
1205                                 }
1206                         }
1207                         else
1208                         {
1209                                 /* just send the function definition to output */
1210                                 fputs(func_buf->data, output);
1211                         }
1212
1213                         if (is_pager)
1214                                 ClosePager(output);
1215                 }
1216
1217                 if (func)
1218                         free(func);
1219                 destroyPQExpBuffer(func_buf);
1220         }
1221
1222         /* \t -- turn off headers and row count */
1223         else if (strcmp(cmd, "t") == 0)
1224         {
1225                 char       *opt = psql_scan_slash_option(scan_state,
1226                                                                                                  OT_NORMAL, NULL, true);
1227
1228                 success = do_pset("tuples_only", opt, &pset.popt, pset.quiet);
1229                 free(opt);
1230         }
1231
1232         /* \T -- define html <table ...> attributes */
1233         else if (strcmp(cmd, "T") == 0)
1234         {
1235                 char       *value = psql_scan_slash_option(scan_state,
1236                                                                                                    OT_NORMAL, NULL, false);
1237
1238                 success = do_pset("tableattr", value, &pset.popt, pset.quiet);
1239                 free(value);
1240         }
1241
1242         /* \timing -- toggle timing of queries */
1243         else if (strcmp(cmd, "timing") == 0)
1244         {
1245                 char       *opt = psql_scan_slash_option(scan_state,
1246                                                                                                  OT_NORMAL, NULL, false);
1247
1248                 if (opt)
1249                         pset.timing = ParseVariableBool(opt);
1250                 else
1251                         pset.timing = !pset.timing;
1252                 if (!pset.quiet)
1253                 {
1254                         if (pset.timing)
1255                                 puts(_("Timing is on."));
1256                         else
1257                                 puts(_("Timing is off."));
1258                 }
1259                 free(opt);
1260         }
1261
1262         /* \unset */
1263         else if (strcmp(cmd, "unset") == 0)
1264         {
1265                 char       *opt = psql_scan_slash_option(scan_state,
1266                                                                                                  OT_NORMAL, NULL, false);
1267
1268                 if (!opt)
1269                 {
1270                         psql_error("\\%s: missing required argument\n", cmd);
1271                         success = false;
1272                 }
1273                 else if (!SetVariable(pset.vars, opt, NULL))
1274                 {
1275                         psql_error("\\%s: error\n", cmd);
1276                         success = false;
1277                 }
1278                 free(opt);
1279         }
1280
1281         /* \w -- write query buffer to file */
1282         else if (strcmp(cmd, "w") == 0 || strcmp(cmd, "write") == 0)
1283         {
1284                 FILE       *fd = NULL;
1285                 bool            is_pipe = false;
1286                 char       *fname = NULL;
1287
1288                 if (!query_buf)
1289                 {
1290                         psql_error("no query buffer\n");
1291                         status = PSQL_CMD_ERROR;
1292                 }
1293                 else
1294                 {
1295                         fname = psql_scan_slash_option(scan_state,
1296                                                                                    OT_FILEPIPE, NULL, true);
1297                         expand_tilde(&fname);
1298
1299                         if (!fname)
1300                         {
1301                                 psql_error("\\%s: missing required argument\n", cmd);
1302                                 success = false;
1303                         }
1304                         else
1305                         {
1306                                 if (fname[0] == '|')
1307                                 {
1308                                         is_pipe = true;
1309                                         fd = popen(&fname[1], "w");
1310                                 }
1311                                 else
1312                                 {
1313                                         canonicalize_path(fname);
1314                                         fd = fopen(fname, "w");
1315                                 }
1316                                 if (!fd)
1317                                 {
1318                                         psql_error("%s: %s\n", fname, strerror(errno));
1319                                         success = false;
1320                                 }
1321                         }
1322                 }
1323
1324                 if (fd)
1325                 {
1326                         int                     result;
1327
1328                         if (query_buf && query_buf->len > 0)
1329                                 fprintf(fd, "%s\n", query_buf->data);
1330
1331                         if (is_pipe)
1332                                 result = pclose(fd);
1333                         else
1334                                 result = fclose(fd);
1335
1336                         if (result == EOF)
1337                         {
1338                                 psql_error("%s: %s\n", fname, strerror(errno));
1339                                 success = false;
1340                         }
1341                 }
1342
1343                 free(fname);
1344         }
1345
1346         /* \x -- toggle expanded table representation */
1347         else if (strcmp(cmd, "x") == 0)
1348         {
1349                 char       *opt = psql_scan_slash_option(scan_state,
1350                                                                                                  OT_NORMAL, NULL, true);
1351
1352                 success = do_pset("expanded", opt, &pset.popt, pset.quiet);
1353                 free(opt);
1354         }
1355
1356         /* \z -- list table rights (equivalent to \dp) */
1357         else if (strcmp(cmd, "z") == 0)
1358         {
1359                 char       *pattern = psql_scan_slash_option(scan_state,
1360                                                                                                          OT_NORMAL, NULL, true);
1361
1362                 success = permissionsList(pattern);
1363                 if (pattern)
1364                         free(pattern);
1365         }
1366
1367         /* \! -- shell escape */
1368         else if (strcmp(cmd, "!") == 0)
1369         {
1370                 char       *opt = psql_scan_slash_option(scan_state,
1371                                                                                                  OT_WHOLE_LINE, NULL, false);
1372
1373                 success = do_shell(opt);
1374                 free(opt);
1375         }
1376
1377         /* \? -- slash command help */
1378         else if (strcmp(cmd, "?") == 0)
1379                 slashUsage(pset.popt.topt.pager);
1380
1381 #if 0
1382
1383         /*
1384          * These commands don't do anything. I just use them to test the parser.
1385          */
1386         else if (strcmp(cmd, "void") == 0 || strcmp(cmd, "#") == 0)
1387         {
1388                 int                     i = 0;
1389                 char       *value;
1390
1391                 while ((value = psql_scan_slash_option(scan_state,
1392                                                                                            OT_NORMAL, NULL, true)))
1393                 {
1394                         fprintf(stderr, "+ opt(%d) = |%s|\n", i++, value);
1395                         free(value);
1396                 }
1397         }
1398 #endif
1399
1400         else
1401                 status = PSQL_CMD_UNKNOWN;
1402
1403         if (!success)
1404                 status = PSQL_CMD_ERROR;
1405
1406         return status;
1407 }
1408
1409 /*
1410  * Ask the user for a password; 'username' is the username the
1411  * password is for, if one has been explicitly specified. Returns a
1412  * malloc'd string.
1413  */
1414 static char *
1415 prompt_for_password(const char *username)
1416 {
1417         char       *result;
1418
1419         if (username == NULL)
1420                 result = simple_prompt("Password: ", 100, false);
1421         else
1422         {
1423                 char       *prompt_text;
1424
1425                 prompt_text = malloc(strlen(username) + 100);
1426                 snprintf(prompt_text, strlen(username) + 100,
1427                                  _("Password for user %s: "), username);
1428                 result = simple_prompt(prompt_text, 100, false);
1429                 free(prompt_text);
1430         }
1431
1432         return result;
1433 }
1434
1435 static bool
1436 param_is_newly_set(const char *old_val, const char *new_val)
1437 {
1438         if (new_val == NULL)
1439                 return false;
1440
1441         if (old_val == NULL || strcmp(old_val, new_val) != 0)
1442                 return true;
1443
1444         return false;
1445 }
1446
1447 /*
1448  * do_connect -- handler for \connect
1449  *
1450  * Connects to a database with given parameters. If there exists an
1451  * established connection, NULL values will be replaced with the ones
1452  * in the current connection. Otherwise NULL will be passed for that
1453  * parameter to PQconnectdbParams(), so the libpq defaults will be used.
1454  *
1455  * In interactive mode, if connection fails with the given parameters,
1456  * the old connection will be kept.
1457  */
1458 static bool
1459 do_connect(char *dbname, char *user, char *host, char *port)
1460 {
1461         PGconn     *o_conn = pset.db,
1462                            *n_conn;
1463         char       *password = NULL;
1464
1465         if (!dbname)
1466                 dbname = PQdb(o_conn);
1467         if (!user)
1468                 user = PQuser(o_conn);
1469         if (!host)
1470                 host = PQhost(o_conn);
1471         if (!port)
1472                 port = PQport(o_conn);
1473
1474         /*
1475          * If the user asked to be prompted for a password, ask for one now. If
1476          * not, use the password from the old connection, provided the username
1477          * has not changed. Otherwise, try to connect without a password first,
1478          * and then ask for a password if needed.
1479          *
1480          * XXX: this behavior leads to spurious connection attempts recorded in
1481          * the postmaster's log.  But libpq offers no API that would let us obtain
1482          * a password and then continue with the first connection attempt.
1483          */
1484         if (pset.getPassword == TRI_YES)
1485         {
1486                 password = prompt_for_password(user);
1487         }
1488         else if (o_conn && user && strcmp(PQuser(o_conn), user) == 0)
1489         {
1490                 password = strdup(PQpass(o_conn));
1491         }
1492
1493         while (true)
1494         {
1495 #define PARAMS_ARRAY_SIZE       8
1496                 const char **keywords = pg_malloc(PARAMS_ARRAY_SIZE * sizeof(*keywords));
1497                 const char **values = pg_malloc(PARAMS_ARRAY_SIZE * sizeof(*values));
1498
1499                 keywords[0] = "host";
1500                 values[0] = host;
1501                 keywords[1] = "port";
1502                 values[1] = port;
1503                 keywords[2] = "user";
1504                 values[2] = user;
1505                 keywords[3] = "password";
1506                 values[3] = password;
1507                 keywords[4] = "dbname";
1508                 values[4] = dbname;
1509                 keywords[5] = "fallback_application_name";
1510                 values[5] = pset.progname;
1511                 keywords[6] = "client_encoding";
1512                 values[6] = (pset.notty || getenv("PGCLIENTENCODING")) ? NULL : "auto";
1513                 keywords[7] = NULL;
1514                 values[7] = NULL;
1515
1516                 n_conn = PQconnectdbParams(keywords, values, true);
1517
1518                 free(keywords);
1519                 free(values);
1520
1521                 /* We can immediately discard the password -- no longer needed */
1522                 if (password)
1523                         free(password);
1524
1525                 if (PQstatus(n_conn) == CONNECTION_OK)
1526                         break;
1527
1528                 /*
1529                  * Connection attempt failed; either retry the connection attempt with
1530                  * a new password, or give up.
1531                  */
1532                 if (!password && PQconnectionNeedsPassword(n_conn) && pset.getPassword != TRI_NO)
1533                 {
1534                         PQfinish(n_conn);
1535                         password = prompt_for_password(user);
1536                         continue;
1537                 }
1538
1539                 /*
1540                  * Failed to connect to the database. In interactive mode, keep the
1541                  * previous connection to the DB; in scripting mode, close our
1542                  * previous connection as well.
1543                  */
1544                 if (pset.cur_cmd_interactive)
1545                 {
1546                         psql_error("%s", PQerrorMessage(n_conn));
1547
1548                         /* pset.db is left unmodified */
1549                         if (o_conn)
1550                                 fputs(_("Previous connection kept\n"), stderr);
1551                 }
1552                 else
1553                 {
1554                         psql_error("\\connect: %s", PQerrorMessage(n_conn));
1555                         if (o_conn)
1556                         {
1557                                 PQfinish(o_conn);
1558                                 pset.db = NULL;
1559                         }
1560                 }
1561
1562                 PQfinish(n_conn);
1563                 return false;
1564         }
1565
1566         /*
1567          * Replace the old connection with the new one, and update
1568          * connection-dependent variables.
1569          */
1570         PQsetNoticeProcessor(n_conn, NoticeProcessor, NULL);
1571         pset.db = n_conn;
1572         SyncVariables();
1573         connection_warnings(false); /* Must be after SyncVariables */
1574
1575         /* Tell the user about the new connection */
1576         if (!pset.quiet)
1577         {
1578                 if (param_is_newly_set(PQhost(o_conn), PQhost(pset.db)) ||
1579                         param_is_newly_set(PQport(o_conn), PQport(pset.db)))
1580                 {
1581                         char       *host = PQhost(pset.db);
1582
1583                         if (host == NULL)
1584                                 host = DEFAULT_PGSOCKET_DIR;
1585                         /* If the host is an absolute path, the connection is via socket */
1586                         if (is_absolute_path(host))
1587                                 printf(_("You are now connected to database \"%s\" as user \"%s\" via socket in \"%s\" at port \"%s\".\n"),
1588                                            PQdb(pset.db), PQuser(pset.db), host, PQport(pset.db));
1589                         else
1590                                 printf(_("You are now connected to database \"%s\" as user \"%s\" on host \"%s\" at port \"%s\".\n"),
1591                                            PQdb(pset.db), PQuser(pset.db), host, PQport(pset.db));
1592                 }
1593                 else
1594                         printf(_("You are now connected to database \"%s\" as user \"%s\".\n"),
1595                                    PQdb(pset.db), PQuser(pset.db));
1596         }
1597
1598         if (o_conn)
1599                 PQfinish(o_conn);
1600         return true;
1601 }
1602
1603
1604 void
1605 connection_warnings(bool in_startup)
1606 {
1607         if (!pset.quiet && !pset.notty)
1608         {
1609                 int                     client_ver = parse_version(PG_VERSION);
1610
1611                 if (pset.sversion != client_ver)
1612                 {
1613                         const char *server_version;
1614                         char            server_ver_str[16];
1615
1616                         /* Try to get full text form, might include "devel" etc */
1617                         server_version = PQparameterStatus(pset.db, "server_version");
1618                         if (!server_version)
1619                         {
1620                                 snprintf(server_ver_str, sizeof(server_ver_str),
1621                                                  "%d.%d.%d",
1622                                                  pset.sversion / 10000,
1623                                                  (pset.sversion / 100) % 100,
1624                                                  pset.sversion % 100);
1625                                 server_version = server_ver_str;
1626                         }
1627
1628                         printf(_("%s (%s, server %s)\n"),
1629                                    pset.progname, PG_VERSION, server_version);
1630                 }
1631                 /* For version match, only print psql banner on startup. */
1632                 else if (in_startup)
1633                         printf("%s (%s)\n", pset.progname, PG_VERSION);
1634
1635                 if (pset.sversion / 100 != client_ver / 100)
1636                         printf(_("WARNING: %s version %d.%d, server version %d.%d.\n"
1637                                          "         Some psql features might not work.\n"),
1638                                  pset.progname, client_ver / 10000, (client_ver / 100) % 100,
1639                                    pset.sversion / 10000, (pset.sversion / 100) % 100);
1640
1641 #ifdef WIN32
1642                 checkWin32Codepage();
1643 #endif
1644                 printSSLInfo();
1645         }
1646 }
1647
1648
1649 /*
1650  * printSSLInfo
1651  *
1652  * Prints information about the current SSL connection, if SSL is in use
1653  */
1654 static void
1655 printSSLInfo(void)
1656 {
1657 #ifdef USE_SSL
1658         int                     sslbits = -1;
1659         SSL                *ssl;
1660
1661         ssl = PQgetssl(pset.db);
1662         if (!ssl)
1663                 return;                                 /* no SSL */
1664
1665         SSL_get_cipher_bits(ssl, &sslbits);
1666         printf(_("SSL connection (cipher: %s, bits: %d)\n"),
1667                    SSL_get_cipher(ssl), sslbits);
1668 #else
1669
1670         /*
1671          * If psql is compiled without SSL but is using a libpq with SSL, we
1672          * cannot figure out the specifics about the connection. But we know it's
1673          * SSL secured.
1674          */
1675         if (PQgetssl(pset.db))
1676                 printf(_("SSL connection (unknown cipher)\n"));
1677 #endif
1678 }
1679
1680
1681 /*
1682  * checkWin32Codepage
1683  *
1684  * Prints a warning when win32 console codepage differs from Windows codepage
1685  */
1686 #ifdef WIN32
1687 static void
1688 checkWin32Codepage(void)
1689 {
1690         unsigned int wincp,
1691                                 concp;
1692
1693         wincp = GetACP();
1694         concp = GetConsoleCP();
1695         if (wincp != concp)
1696         {
1697                 printf(_("WARNING: Console code page (%u) differs from Windows code page (%u)\n"
1698                                  "         8-bit characters might not work correctly. See psql reference\n"
1699                                  "         page \"Notes for Windows users\" for details.\n"),
1700                            concp, wincp);
1701         }
1702 }
1703 #endif
1704
1705
1706 /*
1707  * SyncVariables
1708  *
1709  * Make psql's internal variables agree with connection state upon
1710  * establishing a new connection.
1711  */
1712 void
1713 SyncVariables(void)
1714 {
1715         /* get stuff from connection */
1716         pset.encoding = PQclientEncoding(pset.db);
1717         pset.popt.topt.encoding = pset.encoding;
1718         pset.sversion = PQserverVersion(pset.db);
1719
1720         SetVariable(pset.vars, "DBNAME", PQdb(pset.db));
1721         SetVariable(pset.vars, "USER", PQuser(pset.db));
1722         SetVariable(pset.vars, "HOST", PQhost(pset.db));
1723         SetVariable(pset.vars, "PORT", PQport(pset.db));
1724         SetVariable(pset.vars, "ENCODING", pg_encoding_to_char(pset.encoding));
1725
1726         /* send stuff to it, too */
1727         PQsetErrorVerbosity(pset.db, pset.verbosity);
1728 }
1729
1730 /*
1731  * UnsyncVariables
1732  *
1733  * Clear variables that should be not be set when there is no connection.
1734  */
1735 void
1736 UnsyncVariables(void)
1737 {
1738         SetVariable(pset.vars, "DBNAME", NULL);
1739         SetVariable(pset.vars, "USER", NULL);
1740         SetVariable(pset.vars, "HOST", NULL);
1741         SetVariable(pset.vars, "PORT", NULL);
1742         SetVariable(pset.vars, "ENCODING", NULL);
1743 }
1744
1745
1746 /*
1747  * do_edit -- handler for \e
1748  *
1749  * If you do not specify a filename, the current query buffer will be copied
1750  * into a temporary one.
1751  */
1752 static bool
1753 editFile(const char *fname, int lineno)
1754 {
1755         const char *editorName;
1756         const char *editor_lineno_arg = NULL;
1757         char       *sys;
1758         int                     result;
1759
1760         psql_assert(fname);
1761
1762         /* Find an editor to use */
1763         editorName = getenv("PSQL_EDITOR");
1764         if (!editorName)
1765                 editorName = getenv("EDITOR");
1766         if (!editorName)
1767                 editorName = getenv("VISUAL");
1768         if (!editorName)
1769                 editorName = DEFAULT_EDITOR;
1770
1771         /* Get line number argument, if we need it. */
1772         if (lineno > 0)
1773         {
1774                 editor_lineno_arg = getenv("PSQL_EDITOR_LINENUMBER_ARG");
1775 #ifdef DEFAULT_EDITOR_LINENUMBER_ARG
1776                 if (!editor_lineno_arg)
1777                         editor_lineno_arg = DEFAULT_EDITOR_LINENUMBER_ARG;
1778 #endif
1779                 if (!editor_lineno_arg)
1780                 {
1781                         psql_error("environment variable PSQL_EDITOR_LINENUMBER_ARG must be set to specify a line number\n");
1782                         return false;
1783                 }
1784         }
1785
1786         /* Allocate sufficient memory for command line. */
1787         if (lineno > 0)
1788                 sys = pg_malloc(strlen(editorName)
1789                                                 + strlen(editor_lineno_arg) + 10                /* for integer */
1790                                                 + 1 + strlen(fname) + 10 + 1);
1791         else
1792                 sys = pg_malloc(strlen(editorName) + strlen(fname) + 10 + 1);
1793
1794         /*
1795          * On Unix the EDITOR value should *not* be quoted, since it might include
1796          * switches, eg, EDITOR="pico -t"; it's up to the user to put quotes in it
1797          * if necessary.  But this policy is not very workable on Windows, due to
1798          * severe brain damage in their command shell plus the fact that standard
1799          * program paths include spaces.
1800          */
1801 #ifndef WIN32
1802         if (lineno > 0)
1803                 sprintf(sys, "exec %s %s%d '%s'",
1804                                 editorName, editor_lineno_arg, lineno, fname);
1805         else
1806                 sprintf(sys, "exec %s '%s'",
1807                                 editorName, fname);
1808 #else
1809         if (lineno > 0)
1810                 sprintf(sys, SYSTEMQUOTE "\"%s\" %s%d \"%s\"" SYSTEMQUOTE,
1811                                 editorName, editor_lineno_arg, lineno, fname);
1812         else
1813                 sprintf(sys, SYSTEMQUOTE "\"%s\" \"%s\"" SYSTEMQUOTE,
1814                                 editorName, fname);
1815 #endif
1816         result = system(sys);
1817         if (result == -1)
1818                 psql_error("could not start editor \"%s\"\n", editorName);
1819         else if (result == 127)
1820                 psql_error("could not start /bin/sh\n");
1821         free(sys);
1822
1823         return result == 0;
1824 }
1825
1826
1827 /* call this one */
1828 static bool
1829 do_edit(const char *filename_arg, PQExpBuffer query_buf,
1830                 int lineno, bool *edited)
1831 {
1832         char            fnametmp[MAXPGPATH];
1833         FILE       *stream = NULL;
1834         const char *fname;
1835         bool            error = false;
1836         int                     fd;
1837
1838         struct stat before,
1839                                 after;
1840
1841         if (filename_arg)
1842                 fname = filename_arg;
1843         else
1844         {
1845                 /* make a temp file to edit */
1846 #ifndef WIN32
1847                 const char *tmpdir = getenv("TMPDIR");
1848
1849                 if (!tmpdir)
1850                         tmpdir = "/tmp";
1851 #else
1852                 char            tmpdir[MAXPGPATH];
1853                 int                     ret;
1854
1855                 ret = GetTempPath(MAXPGPATH, tmpdir);
1856                 if (ret == 0 || ret > MAXPGPATH)
1857                 {
1858                         psql_error("could not locate temporary directory: %s\n",
1859                                            !ret ? strerror(errno) : "");
1860                         return false;
1861                 }
1862
1863                 /*
1864                  * No canonicalize_path() here. EDIT.EXE run from CMD.EXE prepends the
1865                  * current directory to the supplied path unless we use only
1866                  * backslashes, so we do that.
1867                  */
1868 #endif
1869 #ifndef WIN32
1870                 snprintf(fnametmp, sizeof(fnametmp), "%s%spsql.edit.%d", tmpdir,
1871                                  "/", (int) getpid());
1872 #else
1873                 snprintf(fnametmp, sizeof(fnametmp), "%s%spsql.edit.%d", tmpdir,
1874                            "" /* trailing separator already present */ , (int) getpid());
1875 #endif
1876
1877                 fname = (const char *) fnametmp;
1878
1879                 fd = open(fname, O_WRONLY | O_CREAT | O_EXCL, 0600);
1880                 if (fd != -1)
1881                         stream = fdopen(fd, "w");
1882
1883                 if (fd == -1 || !stream)
1884                 {
1885                         psql_error("could not open temporary file \"%s\": %s\n", fname, strerror(errno));
1886                         error = true;
1887                 }
1888                 else
1889                 {
1890                         unsigned int ql = query_buf->len;
1891
1892                         if (ql == 0 || query_buf->data[ql - 1] != '\n')
1893                         {
1894                                 appendPQExpBufferChar(query_buf, '\n');
1895                                 ql++;
1896                         }
1897
1898                         if (fwrite(query_buf->data, 1, ql, stream) != ql)
1899                         {
1900                                 psql_error("%s: %s\n", fname, strerror(errno));
1901                                 fclose(stream);
1902                                 remove(fname);
1903                                 error = true;
1904                         }
1905                         else if (fclose(stream) != 0)
1906                         {
1907                                 psql_error("%s: %s\n", fname, strerror(errno));
1908                                 remove(fname);
1909                                 error = true;
1910                         }
1911                 }
1912         }
1913
1914         if (!error && stat(fname, &before) != 0)
1915         {
1916                 psql_error("%s: %s\n", fname, strerror(errno));
1917                 error = true;
1918         }
1919
1920         /* call editor */
1921         if (!error)
1922                 error = !editFile(fname, lineno);
1923
1924         if (!error && stat(fname, &after) != 0)
1925         {
1926                 psql_error("%s: %s\n", fname, strerror(errno));
1927                 error = true;
1928         }
1929
1930         if (!error && before.st_mtime != after.st_mtime)
1931         {
1932                 stream = fopen(fname, PG_BINARY_R);
1933                 if (!stream)
1934                 {
1935                         psql_error("%s: %s\n", fname, strerror(errno));
1936                         error = true;
1937                 }
1938                 else
1939                 {
1940                         /* read file back into query_buf */
1941                         char            line[1024];
1942
1943                         resetPQExpBuffer(query_buf);
1944                         while (fgets(line, sizeof(line), stream) != NULL)
1945                                 appendPQExpBufferStr(query_buf, line);
1946
1947                         if (ferror(stream))
1948                         {
1949                                 psql_error("%s: %s\n", fname, strerror(errno));
1950                                 error = true;
1951                         }
1952                         else if (edited)
1953                         {
1954                                 *edited = true;
1955                         }
1956
1957                         fclose(stream);
1958                 }
1959         }
1960
1961         /* remove temp file */
1962         if (!filename_arg)
1963         {
1964                 if (remove(fname) == -1)
1965                 {
1966                         psql_error("%s: %s\n", fname, strerror(errno));
1967                         error = true;
1968                 }
1969         }
1970
1971         return !error;
1972 }
1973
1974
1975
1976 /*
1977  * process_file
1978  *
1979  * Read commands from filename and then them to the main processing loop
1980  * Handler for \i and \ir, but can be used for other things as well.  Returns
1981  * MainLoop() error code.
1982  *
1983  * If use_relative_path is true and filename is not an absolute path, then open
1984  * the file from where the currently processed file (if any) is located.
1985  */
1986 int
1987 process_file(char *filename, bool single_txn, bool use_relative_path)
1988 {
1989         FILE       *fd;
1990         int                     result;
1991         char       *oldfilename;
1992         char            relpath[MAXPGPATH];
1993         PGresult   *res;
1994
1995         if (!filename)
1996                 return EXIT_FAILURE;
1997
1998         if (strcmp(filename, "-") != 0)
1999         {
2000                 canonicalize_path(filename);
2001
2002                 /*
2003                  * If we were asked to resolve the pathname relative to the location
2004                  * of the currently executing script, and there is one, and this is
2005                  * a relative pathname, then prepend all but the last pathname
2006                  * component of the current script to this pathname.
2007                  */
2008                 if (use_relative_path && pset.inputfile && !is_absolute_path(filename)
2009                         && !has_drive_prefix(filename))
2010                 {
2011                         snprintf(relpath, MAXPGPATH, "%s", pset.inputfile);
2012                         get_parent_directory(relpath);
2013                         join_path_components(relpath, relpath, filename);
2014                         canonicalize_path(relpath);
2015
2016                         filename = relpath;
2017                 }
2018
2019                 fd = fopen(filename, PG_BINARY_R);
2020         }
2021         else
2022                 fd = stdin;
2023
2024         if (!fd)
2025         {
2026                 psql_error("%s: %s\n", filename, strerror(errno));
2027                 return EXIT_FAILURE;
2028         }
2029
2030         oldfilename = pset.inputfile;
2031         pset.inputfile = filename;
2032
2033         if (single_txn)
2034         {
2035                 if ((res = PSQLexec("BEGIN", false)) == NULL)
2036                 {
2037                         if (pset.on_error_stop)
2038                         {
2039                                 result = EXIT_USER;
2040                                 goto error;
2041                         }
2042                 }
2043                 else
2044                         PQclear(res);
2045         }
2046
2047         result = MainLoop(fd);
2048
2049         if (single_txn)
2050         {
2051                 if ((res = PSQLexec("COMMIT", false)) == NULL)
2052                 {
2053                         if (pset.on_error_stop)
2054                         {
2055                                 result = EXIT_USER;
2056                                 goto error;
2057                         }
2058                 }
2059                 else
2060                         PQclear(res);
2061         }
2062
2063 error:
2064         if (fd != stdin)
2065                 fclose(fd);
2066
2067         pset.inputfile = oldfilename;
2068         return result;
2069 }
2070
2071
2072
2073 /*
2074  * do_pset
2075  *
2076  */
2077 static const char *
2078 _align2string(enum printFormat in)
2079 {
2080         switch (in)
2081         {
2082                 case PRINT_NOTHING:
2083                         return "nothing";
2084                         break;
2085                 case PRINT_UNALIGNED:
2086                         return "unaligned";
2087                         break;
2088                 case PRINT_ALIGNED:
2089                         return "aligned";
2090                         break;
2091                 case PRINT_WRAPPED:
2092                         return "wrapped";
2093                         break;
2094                 case PRINT_HTML:
2095                         return "html";
2096                         break;
2097                 case PRINT_LATEX:
2098                         return "latex";
2099                         break;
2100                 case PRINT_TROFF_MS:
2101                         return "troff-ms";
2102                         break;
2103         }
2104         return "unknown";
2105 }
2106
2107
2108 bool
2109 do_pset(const char *param, const char *value, printQueryOpt *popt, bool quiet)
2110 {
2111         size_t          vallen = 0;
2112
2113         psql_assert(param);
2114
2115         if (value)
2116                 vallen = strlen(value);
2117
2118         /* set format */
2119         if (strcmp(param, "format") == 0)
2120         {
2121                 if (!value)
2122                         ;
2123                 else if (pg_strncasecmp("unaligned", value, vallen) == 0)
2124                         popt->topt.format = PRINT_UNALIGNED;
2125                 else if (pg_strncasecmp("aligned", value, vallen) == 0)
2126                         popt->topt.format = PRINT_ALIGNED;
2127                 else if (pg_strncasecmp("wrapped", value, vallen) == 0)
2128                         popt->topt.format = PRINT_WRAPPED;
2129                 else if (pg_strncasecmp("html", value, vallen) == 0)
2130                         popt->topt.format = PRINT_HTML;
2131                 else if (pg_strncasecmp("latex", value, vallen) == 0)
2132                         popt->topt.format = PRINT_LATEX;
2133                 else if (pg_strncasecmp("troff-ms", value, vallen) == 0)
2134                         popt->topt.format = PRINT_TROFF_MS;
2135                 else
2136                 {
2137                         psql_error("\\pset: allowed formats are unaligned, aligned, wrapped, html, latex, troff-ms\n");
2138                         return false;
2139                 }
2140
2141                 if (!quiet)
2142                         printf(_("Output format is %s.\n"), _align2string(popt->topt.format));
2143         }
2144
2145         /* set table line style */
2146         else if (strcmp(param, "linestyle") == 0)
2147         {
2148                 if (!value)
2149                         ;
2150                 else if (pg_strncasecmp("ascii", value, vallen) == 0)
2151                         popt->topt.line_style = &pg_asciiformat;
2152                 else if (pg_strncasecmp("old-ascii", value, vallen) == 0)
2153                         popt->topt.line_style = &pg_asciiformat_old;
2154                 else if (pg_strncasecmp("unicode", value, vallen) == 0)
2155                         popt->topt.line_style = &pg_utf8format;
2156                 else
2157                 {
2158                         psql_error("\\pset: allowed line styles are ascii, old-ascii, unicode\n");
2159                         return false;
2160                 }
2161
2162                 if (!quiet)
2163                         printf(_("Line style is %s.\n"),
2164                                    get_line_style(&popt->topt)->name);
2165         }
2166
2167         /* set border style/width */
2168         else if (strcmp(param, "border") == 0)
2169         {
2170                 if (value)
2171                         popt->topt.border = atoi(value);
2172
2173                 if (!quiet)
2174                         printf(_("Border style is %d.\n"), popt->topt.border);
2175         }
2176
2177         /* set expanded/vertical mode */
2178         else if (strcmp(param, "x") == 0 || strcmp(param, "expanded") == 0 || strcmp(param, "vertical") == 0)
2179         {
2180                 if (value)
2181                         popt->topt.expanded = ParseVariableBool(value);
2182                 else
2183                         popt->topt.expanded = !popt->topt.expanded;
2184                 if (!quiet)
2185                         printf(popt->topt.expanded
2186                                    ? _("Expanded display is on.\n")
2187                                    : _("Expanded display is off.\n"));
2188         }
2189
2190         /* locale-aware numeric output */
2191         else if (strcmp(param, "numericlocale") == 0)
2192         {
2193                 if (value)
2194                         popt->topt.numericLocale = ParseVariableBool(value);
2195                 else
2196                         popt->topt.numericLocale = !popt->topt.numericLocale;
2197                 if (!quiet)
2198                 {
2199                         if (popt->topt.numericLocale)
2200                                 puts(_("Showing locale-adjusted numeric output."));
2201                         else
2202                                 puts(_("Locale-adjusted numeric output is off."));
2203                 }
2204         }
2205
2206         /* null display */
2207         else if (strcmp(param, "null") == 0)
2208         {
2209                 if (value)
2210                 {
2211                         free(popt->nullPrint);
2212                         popt->nullPrint = pg_strdup(value);
2213                 }
2214                 if (!quiet)
2215                         printf(_("Null display is \"%s\".\n"), popt->nullPrint ? popt->nullPrint : "");
2216         }
2217
2218         /* field separator for unaligned text */
2219         else if (strcmp(param, "fieldsep") == 0)
2220         {
2221                 if (value)
2222                 {
2223                         free(popt->topt.fieldSep);
2224                         popt->topt.fieldSep = pg_strdup(value);
2225                 }
2226                 if (!quiet)
2227                         printf(_("Field separator is \"%s\".\n"), popt->topt.fieldSep);
2228         }
2229
2230         /* record separator for unaligned text */
2231         else if (strcmp(param, "recordsep") == 0)
2232         {
2233                 if (value)
2234                 {
2235                         free(popt->topt.recordSep);
2236                         popt->topt.recordSep = pg_strdup(value);
2237                 }
2238                 if (!quiet)
2239                 {
2240                         if (strcmp(popt->topt.recordSep, "\n") == 0)
2241                                 printf(_("Record separator is <newline>."));
2242                         else
2243                                 printf(_("Record separator is \"%s\".\n"), popt->topt.recordSep);
2244                 }
2245         }
2246
2247         /* toggle between full and tuples-only format */
2248         else if (strcmp(param, "t") == 0 || strcmp(param, "tuples_only") == 0)
2249         {
2250                 if (value)
2251                         popt->topt.tuples_only = ParseVariableBool(value);
2252                 else
2253                         popt->topt.tuples_only = !popt->topt.tuples_only;
2254                 if (!quiet)
2255                 {
2256                         if (popt->topt.tuples_only)
2257                                 puts(_("Showing only tuples."));
2258                         else
2259                                 puts(_("Tuples only is off."));
2260                 }
2261         }
2262
2263         /* set title override */
2264         else if (strcmp(param, "title") == 0)
2265         {
2266                 free(popt->title);
2267                 if (!value)
2268                         popt->title = NULL;
2269                 else
2270                         popt->title = pg_strdup(value);
2271
2272                 if (!quiet)
2273                 {
2274                         if (popt->title)
2275                                 printf(_("Title is \"%s\".\n"), popt->title);
2276                         else
2277                                 printf(_("Title is unset.\n"));
2278                 }
2279         }
2280
2281         /* set HTML table tag options */
2282         else if (strcmp(param, "T") == 0 || strcmp(param, "tableattr") == 0)
2283         {
2284                 free(popt->topt.tableAttr);
2285                 if (!value)
2286                         popt->topt.tableAttr = NULL;
2287                 else
2288                         popt->topt.tableAttr = pg_strdup(value);
2289
2290                 if (!quiet)
2291                 {
2292                         if (popt->topt.tableAttr)
2293                                 printf(_("Table attribute is \"%s\".\n"), popt->topt.tableAttr);
2294                         else
2295                                 printf(_("Table attributes unset.\n"));
2296                 }
2297         }
2298
2299         /* toggle use of pager */
2300         else if (strcmp(param, "pager") == 0)
2301         {
2302                 if (value && pg_strcasecmp(value, "always") == 0)
2303                         popt->topt.pager = 2;
2304                 else if (value)
2305                         if (ParseVariableBool(value))
2306                                 popt->topt.pager = 1;
2307                         else
2308                                 popt->topt.pager = 0;
2309                 else if (popt->topt.pager == 1)
2310                         popt->topt.pager = 0;
2311                 else
2312                         popt->topt.pager = 1;
2313                 if (!quiet)
2314                 {
2315                         if (popt->topt.pager == 1)
2316                                 puts(_("Pager is used for long output."));
2317                         else if (popt->topt.pager == 2)
2318                                 puts(_("Pager is always used."));
2319                         else
2320                                 puts(_("Pager usage is off."));
2321                 }
2322         }
2323
2324         /* disable "(x rows)" footer */
2325         else if (strcmp(param, "footer") == 0)
2326         {
2327                 if (value)
2328                         popt->default_footer = ParseVariableBool(value);
2329                 else
2330                         popt->default_footer = !popt->default_footer;
2331                 if (!quiet)
2332                 {
2333                         if (popt->default_footer)
2334                                 puts(_("Default footer is on."));
2335                         else
2336                                 puts(_("Default footer is off."));
2337                 }
2338         }
2339
2340         /* set border style/width */
2341         else if (strcmp(param, "columns") == 0)
2342         {
2343                 if (value)
2344                         popt->topt.columns = atoi(value);
2345
2346                 if (!quiet)
2347                         printf(_("Target width for \"wrapped\" format is %d.\n"), popt->topt.columns);
2348         }
2349
2350         else
2351         {
2352                 psql_error("\\pset: unknown option: %s\n", param);
2353                 return false;
2354         }
2355
2356         return true;
2357 }
2358
2359
2360
2361 #ifndef WIN32
2362 #define DEFAULT_SHELL "/bin/sh"
2363 #else
2364 /*
2365  *      CMD.EXE is in different places in different Win32 releases so we
2366  *      have to rely on the path to find it.
2367  */
2368 #define DEFAULT_SHELL "cmd.exe"
2369 #endif
2370
2371 static bool
2372 do_shell(const char *command)
2373 {
2374         int                     result;
2375
2376         if (!command)
2377         {
2378                 char       *sys;
2379                 const char *shellName;
2380
2381                 shellName = getenv("SHELL");
2382 #ifdef WIN32
2383                 if (shellName == NULL)
2384                         shellName = getenv("COMSPEC");
2385 #endif
2386                 if (shellName == NULL)
2387                         shellName = DEFAULT_SHELL;
2388
2389                 sys = pg_malloc(strlen(shellName) + 16);
2390 #ifndef WIN32
2391                 sprintf(sys,
2392                 /* See EDITOR handling comment for an explaination */
2393                                 "exec %s", shellName);
2394 #else
2395                 /* See EDITOR handling comment for an explaination */
2396                 sprintf(sys, SYSTEMQUOTE "\"%s\"" SYSTEMQUOTE, shellName);
2397 #endif
2398                 result = system(sys);
2399                 free(sys);
2400         }
2401         else
2402                 result = system(command);
2403
2404         if (result == 127 || result == -1)
2405         {
2406                 psql_error("\\!: failed\n");
2407                 return false;
2408         }
2409         return true;
2410 }
2411
2412 /*
2413  * This function takes a function description, e.g. "x" or "x(int)", and
2414  * issues a query on the given connection to retrieve the function's OID
2415  * using a cast to regproc or regprocedure (as appropriate). The result,
2416  * if there is one, is returned at *foid.  Note that we'll fail if the
2417  * function doesn't exist OR if there are multiple matching candidates
2418  * OR if there's something syntactically wrong with the function description;
2419  * unfortunately it can be hard to tell the difference.
2420  */
2421 static bool
2422 lookup_function_oid(PGconn *conn, const char *desc, Oid *foid)
2423 {
2424         bool            result = true;
2425         PQExpBuffer query;
2426         PGresult   *res;
2427
2428         query = createPQExpBuffer();
2429         printfPQExpBuffer(query, "SELECT ");
2430         appendStringLiteralConn(query, desc, conn);
2431         appendPQExpBuffer(query, "::pg_catalog.%s::pg_catalog.oid",
2432                                           strchr(desc, '(') ? "regprocedure" : "regproc");
2433
2434         res = PQexec(conn, query->data);
2435         if (PQresultStatus(res) == PGRES_TUPLES_OK && PQntuples(res) == 1)
2436                 *foid = atooid(PQgetvalue(res, 0, 0));
2437         else
2438         {
2439                 minimal_error_message(res);
2440                 result = false;
2441         }
2442
2443         PQclear(res);
2444         destroyPQExpBuffer(query);
2445
2446         return result;
2447 }
2448
2449 /*
2450  * Fetches the "CREATE OR REPLACE FUNCTION ..." command that describes the
2451  * function with the given OID.  If successful, the result is stored in buf.
2452  */
2453 static bool
2454 get_create_function_cmd(PGconn *conn, Oid oid, PQExpBuffer buf)
2455 {
2456         bool            result = true;
2457         PQExpBuffer query;
2458         PGresult   *res;
2459
2460         query = createPQExpBuffer();
2461         printfPQExpBuffer(query, "SELECT pg_catalog.pg_get_functiondef(%u)", oid);
2462
2463         res = PQexec(conn, query->data);
2464         if (PQresultStatus(res) == PGRES_TUPLES_OK && PQntuples(res) == 1)
2465         {
2466                 resetPQExpBuffer(buf);
2467                 appendPQExpBufferStr(buf, PQgetvalue(res, 0, 0));
2468         }
2469         else
2470         {
2471                 minimal_error_message(res);
2472                 result = false;
2473         }
2474
2475         PQclear(res);
2476         destroyPQExpBuffer(query);
2477
2478         return result;
2479 }
2480
2481 /*
2482  * If the given argument of \ef ends with a line number, delete the line
2483  * number from the argument string and return it as an integer.  (We need
2484  * this kluge because we're too lazy to parse \ef's function name argument
2485  * carefully --- we just slop it up in OT_WHOLE_LINE mode.)
2486  *
2487  * Returns -1 if no line number is present, 0 on error, or a positive value
2488  * on success.
2489  */
2490 static int
2491 strip_lineno_from_funcdesc(char *func)
2492 {
2493         char       *c;
2494         int                     lineno;
2495
2496         if (!func || func[0] == '\0')
2497                 return -1;
2498
2499         c = func + strlen(func) - 1;
2500
2501         /*
2502          * This business of parsing backwards is dangerous as can be in a
2503          * multibyte environment: there is no reason to believe that we are
2504          * looking at the first byte of a character, nor are we necessarily
2505          * working in a "safe" encoding.  Fortunately the bitpatterns we are
2506          * looking for are unlikely to occur as non-first bytes, but beware of
2507          * trying to expand the set of cases that can be recognized.  We must
2508          * guard the <ctype.h> macros by using isascii() first, too.
2509          */
2510
2511         /* skip trailing whitespace */
2512         while (c > func && isascii((unsigned char) *c) && isspace((unsigned char) *c))
2513                 c--;
2514
2515         /* must have a digit as last non-space char */
2516         if (c == func || !isascii((unsigned char) *c) || !isdigit((unsigned char) *c))
2517                 return -1;
2518
2519         /* find start of digit string */
2520         while (c > func && isascii((unsigned char) *c) && isdigit((unsigned char) *c))
2521                 c--;
2522
2523         /* digits must be separated from func name by space or closing paren */
2524         /* notice also that we are not allowing an empty func name ... */
2525         if (c == func || !isascii((unsigned char) *c) ||
2526                 !(isspace((unsigned char) *c) || *c == ')'))
2527                 return -1;
2528
2529         /* parse digit string */
2530         c++;
2531         lineno = atoi(c);
2532         if (lineno < 1)
2533         {
2534                 psql_error("invalid line number: %s\n", c);
2535                 return 0;
2536         }
2537
2538         /* strip digit string from func */
2539         *c = '\0';
2540
2541         return lineno;
2542 }
2543
2544 /*
2545  * Report just the primary error; this is to avoid cluttering the output
2546  * with, for instance, a redisplay of the internally generated query
2547  */
2548 static void
2549 minimal_error_message(PGresult *res)
2550 {
2551         PQExpBuffer msg;
2552         const char *fld;
2553
2554         msg = createPQExpBuffer();
2555
2556         fld = PQresultErrorField(res, PG_DIAG_SEVERITY);
2557         if (fld)
2558                 printfPQExpBuffer(msg, "%s:  ", fld);
2559         else
2560                 printfPQExpBuffer(msg, "ERROR:  ");
2561         fld = PQresultErrorField(res, PG_DIAG_MESSAGE_PRIMARY);
2562         if (fld)
2563                 appendPQExpBufferStr(msg, fld);
2564         else
2565                 appendPQExpBufferStr(msg, "(not available)");
2566         appendPQExpBufferStr(msg, "\n");
2567
2568         psql_error("%s", msg->data);
2569
2570         destroyPQExpBuffer(msg);
2571 }