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