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