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