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