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