OSDN Git Service

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