Header And Logo

PostgreSQL
| The world's most advanced open source database.

command.c

Go to the documentation of this file.
00001 /*
00002  * psql - the PostgreSQL interactive terminal
00003  *
00004  * Copyright (c) 2000-2013, PostgreSQL Global Development Group
00005  *
00006  * src/bin/psql/command.c
00007  */
00008 #include "postgres_fe.h"
00009 #include "command.h"
00010 
00011 #ifdef __BORLANDC__             /* needed for BCC */
00012 #undef mkdir
00013 #endif
00014 
00015 #include <ctype.h>
00016 #include <time.h>
00017 #ifdef HAVE_PWD_H
00018 #include <pwd.h>
00019 #endif
00020 #ifndef WIN32
00021 #include <sys/types.h>          /* for umask() */
00022 #include <sys/stat.h>           /* for stat() */
00023 #include <fcntl.h>              /* open() flags */
00024 #include <unistd.h>             /* for geteuid(), getpid(), stat() */
00025 #else
00026 #include <win32.h>
00027 #include <io.h>
00028 #include <fcntl.h>
00029 #include <direct.h>
00030 #include <sys/types.h>          /* for umask() */
00031 #include <sys/stat.h>           /* for stat() */
00032 #endif
00033 #ifdef USE_SSL
00034 #include <openssl/ssl.h>
00035 #endif
00036 
00037 #include "portability/instr_time.h"
00038 
00039 #include "libpq-fe.h"
00040 #include "pqexpbuffer.h"
00041 #include "dumputils.h"
00042 
00043 #include "common.h"
00044 #include "copy.h"
00045 #include "describe.h"
00046 #include "help.h"
00047 #include "input.h"
00048 #include "large_obj.h"
00049 #include "mainloop.h"
00050 #include "print.h"
00051 #include "psqlscan.h"
00052 #include "settings.h"
00053 #include "variables.h"
00054 
00055 
00056 /* functions for use in this file */
00057 static backslashResult exec_command(const char *cmd,
00058              PsqlScanState scan_state,
00059              PQExpBuffer query_buf);
00060 static bool do_edit(const char *filename_arg, PQExpBuffer query_buf,
00061         int lineno, bool *edited);
00062 static bool do_connect(char *dbname, char *user, char *host, char *port);
00063 static bool do_shell(const char *command);
00064 static bool do_watch(PQExpBuffer query_buf, long sleep);
00065 static bool lookup_function_oid(PGconn *conn, const char *desc, Oid *foid);
00066 static bool get_create_function_cmd(PGconn *conn, Oid oid, PQExpBuffer buf);
00067 static int  strip_lineno_from_funcdesc(char *func);
00068 static void minimal_error_message(PGresult *res);
00069 
00070 static void printSSLInfo(void);
00071 
00072 #ifdef WIN32
00073 static void checkWin32Codepage(void);
00074 #endif
00075 
00076 
00077 
00078 /*----------
00079  * HandleSlashCmds:
00080  *
00081  * Handles all the different commands that start with '\'.
00082  * Ordinarily called by MainLoop().
00083  *
00084  * scan_state is a lexer working state that is set to continue scanning
00085  * just after the '\'.  The lexer is advanced past the command and all
00086  * arguments on return.
00087  *
00088  * 'query_buf' contains the query-so-far, which may be modified by
00089  * execution of the backslash command (for example, \r clears it).
00090  * query_buf can be NULL if there is no query so far.
00091  *
00092  * Returns a status code indicating what action is desired, see command.h.
00093  *----------
00094  */
00095 
00096 backslashResult
00097 HandleSlashCmds(PsqlScanState scan_state,
00098                 PQExpBuffer query_buf)
00099 {
00100     backslashResult status = PSQL_CMD_SKIP_LINE;
00101     char       *cmd;
00102     char       *arg;
00103 
00104     Assert(scan_state != NULL);
00105 
00106     /* Parse off the command name */
00107     cmd = psql_scan_slash_command(scan_state);
00108 
00109     /* And try to execute it */
00110     status = exec_command(cmd, scan_state, query_buf);
00111 
00112     if (status == PSQL_CMD_UNKNOWN)
00113     {
00114         if (pset.cur_cmd_interactive)
00115             psql_error("Invalid command \\%s. Try \\? for help.\n", cmd);
00116         else
00117             psql_error("invalid command \\%s\n", cmd);
00118         status = PSQL_CMD_ERROR;
00119     }
00120 
00121     if (status != PSQL_CMD_ERROR)
00122     {
00123         /* eat any remaining arguments after a valid command */
00124         /* note we suppress evaluation of backticks here */
00125         while ((arg = psql_scan_slash_option(scan_state,
00126                                              OT_NO_EVAL, NULL, false)))
00127         {
00128             psql_error("\\%s: extra argument \"%s\" ignored\n", cmd, arg);
00129             free(arg);
00130         }
00131     }
00132     else
00133     {
00134         /* silently throw away rest of line after an erroneous command */
00135         while ((arg = psql_scan_slash_option(scan_state,
00136                                              OT_WHOLE_LINE, NULL, false)))
00137             free(arg);
00138     }
00139 
00140     /* if there is a trailing \\, swallow it */
00141     psql_scan_slash_command_end(scan_state);
00142 
00143     free(cmd);
00144 
00145     /* some commands write to queryFout, so make sure output is sent */
00146     fflush(pset.queryFout);
00147 
00148     return status;
00149 }
00150 
00151 /*
00152  * Read and interpret an argument to the \connect slash command.
00153  */
00154 static char *
00155 read_connect_arg(PsqlScanState scan_state)
00156 {
00157     char       *result;
00158     char        quote;
00159 
00160     /*
00161      * Ideally we should treat the arguments as SQL identifiers.  But for
00162      * backwards compatibility with 7.2 and older pg_dump files, we have to
00163      * take unquoted arguments verbatim (don't downcase them). For now,
00164      * double-quoted arguments may be stripped of double quotes (as if SQL
00165      * identifiers).  By 7.4 or so, pg_dump files can be expected to
00166      * double-quote all mixed-case \connect arguments, and then we can get rid
00167      * of OT_SQLIDHACK.
00168      */
00169     result = psql_scan_slash_option(scan_state, OT_SQLIDHACK, &quote, true);
00170 
00171     if (!result)
00172         return NULL;
00173 
00174     if (quote)
00175         return result;
00176 
00177     if (*result == '\0' || strcmp(result, "-") == 0)
00178         return NULL;
00179 
00180     return result;
00181 }
00182 
00183 
00184 /*
00185  * Subroutine to actually try to execute a backslash command.
00186  */
00187 static backslashResult
00188 exec_command(const char *cmd,
00189              PsqlScanState scan_state,
00190              PQExpBuffer query_buf)
00191 {
00192     bool        success = true; /* indicate here if the command ran ok or
00193                                  * failed */
00194     backslashResult status = PSQL_CMD_SKIP_LINE;
00195 
00196     /*
00197      * \a -- toggle field alignment This makes little sense but we keep it
00198      * around.
00199      */
00200     if (strcmp(cmd, "a") == 0)
00201     {
00202         if (pset.popt.topt.format != PRINT_ALIGNED)
00203             success = do_pset("format", "aligned", &pset.popt, pset.quiet);
00204         else
00205             success = do_pset("format", "unaligned", &pset.popt, pset.quiet);
00206     }
00207 
00208     /* \C -- override table title (formerly change HTML caption) */
00209     else if (strcmp(cmd, "C") == 0)
00210     {
00211         char       *opt = psql_scan_slash_option(scan_state,
00212                                                  OT_NORMAL, NULL, true);
00213 
00214         success = do_pset("title", opt, &pset.popt, pset.quiet);
00215         free(opt);
00216     }
00217 
00218     /*
00219      * \c or \connect -- connect to database using the specified parameters.
00220      *
00221      * \c dbname user host port
00222      *
00223      * If any of these parameters are omitted or specified as '-', the current
00224      * value of the parameter will be used instead. If the parameter has no
00225      * current value, the default value for that parameter will be used. Some
00226      * examples:
00227      *
00228      * \c - - hst       Connect to current database on current port of host
00229      * "hst" as current user. \c - usr - prt   Connect to current database on
00230      * "prt" port of current host as user "usr". \c dbs           Connect to
00231      * "dbs" database on current port of current host as current user.
00232      */
00233     else if (strcmp(cmd, "c") == 0 || strcmp(cmd, "connect") == 0)
00234     {
00235         char       *opt1,
00236                    *opt2,
00237                    *opt3,
00238                    *opt4;
00239 
00240         opt1 = read_connect_arg(scan_state);
00241         opt2 = read_connect_arg(scan_state);
00242         opt3 = read_connect_arg(scan_state);
00243         opt4 = read_connect_arg(scan_state);
00244 
00245         success = do_connect(opt1, opt2, opt3, opt4);
00246 
00247         free(opt1);
00248         free(opt2);
00249         free(opt3);
00250         free(opt4);
00251     }
00252 
00253     /* \cd */
00254     else if (strcmp(cmd, "cd") == 0)
00255     {
00256         char       *opt = psql_scan_slash_option(scan_state,
00257                                                  OT_NORMAL, NULL, true);
00258         char       *dir;
00259 
00260         if (opt)
00261             dir = opt;
00262         else
00263         {
00264 #ifndef WIN32
00265             struct passwd *pw;
00266 
00267             pw = getpwuid(geteuid());
00268             if (!pw)
00269             {
00270                 psql_error("could not get home directory: %s\n", strerror(errno));
00271                 exit(EXIT_FAILURE);
00272             }
00273             dir = pw->pw_dir;
00274 #else                           /* WIN32 */
00275 
00276             /*
00277              * On Windows, 'cd' without arguments prints the current
00278              * directory, so if someone wants to code this here instead...
00279              */
00280             dir = "/";
00281 #endif   /* WIN32 */
00282         }
00283 
00284         if (chdir(dir) == -1)
00285         {
00286             psql_error("\\%s: could not change directory to \"%s\": %s\n",
00287                        cmd, dir, strerror(errno));
00288             success = false;
00289         }
00290 
00291         if (pset.dirname)
00292             free(pset.dirname);
00293         pset.dirname = pg_strdup(dir);
00294         canonicalize_path(pset.dirname);
00295 
00296         if (opt)
00297             free(opt);
00298     }
00299 
00300     /* \conninfo -- display information about the current connection */
00301     else if (strcmp(cmd, "conninfo") == 0)
00302     {
00303         char       *db = PQdb(pset.db);
00304         char       *host = PQhost(pset.db);
00305 
00306         if (db == NULL)
00307             printf(_("You are currently not connected to a database.\n"));
00308         else
00309         {
00310             if (host == NULL)
00311                 host = DEFAULT_PGSOCKET_DIR;
00312             /* If the host is an absolute path, the connection is via socket */
00313             if (is_absolute_path(host))
00314                 printf(_("You are connected to database \"%s\" as user \"%s\" via socket in \"%s\" at port \"%s\".\n"),
00315                        db, PQuser(pset.db), host, PQport(pset.db));
00316             else
00317                 printf(_("You are connected to database \"%s\" as user \"%s\" on host \"%s\" at port \"%s\".\n"),
00318                        db, PQuser(pset.db), host, PQport(pset.db));
00319             printSSLInfo();
00320         }
00321     }
00322 
00323     /* \copy */
00324     else if (pg_strcasecmp(cmd, "copy") == 0)
00325     {
00326         char       *opt = psql_scan_slash_option(scan_state,
00327                                                  OT_WHOLE_LINE, NULL, false);
00328 
00329         success = do_copy(opt);
00330         free(opt);
00331     }
00332 
00333     /* \copyright */
00334     else if (strcmp(cmd, "copyright") == 0)
00335         print_copyright();
00336 
00337     /* \d* commands */
00338     else if (cmd[0] == 'd')
00339     {
00340         char       *pattern;
00341         bool        show_verbose,
00342                     show_system;
00343 
00344         /* We don't do SQLID reduction on the pattern yet */
00345         pattern = psql_scan_slash_option(scan_state,
00346                                          OT_NORMAL, NULL, true);
00347 
00348         show_verbose = strchr(cmd, '+') ? true : false;
00349         show_system = strchr(cmd, 'S') ? true : false;
00350 
00351         switch (cmd[1])
00352         {
00353             case '\0':
00354             case '+':
00355             case 'S':
00356                 if (pattern)
00357                     success = describeTableDetails(pattern, show_verbose, show_system);
00358                 else
00359                     /* standard listing of interesting things */
00360                     success = listTables("tvmsE", NULL, show_verbose, show_system);
00361                 break;
00362             case 'a':
00363                 success = describeAggregates(pattern, show_verbose, show_system);
00364                 break;
00365             case 'b':
00366                 success = describeTablespaces(pattern, show_verbose);
00367                 break;
00368             case 'c':
00369                 success = listConversions(pattern, show_verbose, show_system);
00370                 break;
00371             case 'C':
00372                 success = listCasts(pattern, show_verbose);
00373                 break;
00374             case 'd':
00375                 if (strncmp(cmd, "ddp", 3) == 0)
00376                     success = listDefaultACLs(pattern);
00377                 else
00378                     success = objectDescription(pattern, show_system);
00379                 break;
00380             case 'D':
00381                 success = listDomains(pattern, show_verbose, show_system);
00382                 break;
00383             case 'f':           /* function subsystem */
00384                 switch (cmd[2])
00385                 {
00386                     case '\0':
00387                     case '+':
00388                     case 'S':
00389                     case 'a':
00390                     case 'n':
00391                     case 't':
00392                     case 'w':
00393                         success = describeFunctions(&cmd[2], pattern, show_verbose, show_system);
00394                         break;
00395                     default:
00396                         status = PSQL_CMD_UNKNOWN;
00397                         break;
00398                 }
00399                 break;
00400             case 'g':
00401                 /* no longer distinct from \du */
00402                 success = describeRoles(pattern, show_verbose);
00403                 break;
00404             case 'l':
00405                 success = do_lo_list();
00406                 break;
00407             case 'L':
00408                 success = listLanguages(pattern, show_verbose, show_system);
00409                 break;
00410             case 'n':
00411                 success = listSchemas(pattern, show_verbose, show_system);
00412                 break;
00413             case 'o':
00414                 success = describeOperators(pattern, show_system);
00415                 break;
00416             case 'O':
00417                 success = listCollations(pattern, show_verbose, show_system);
00418                 break;
00419             case 'p':
00420                 success = permissionsList(pattern);
00421                 break;
00422             case 'T':
00423                 success = describeTypes(pattern, show_verbose, show_system);
00424                 break;
00425             case 't':
00426             case 'v':
00427             case 'm':
00428             case 'i':
00429             case 's':
00430             case 'E':
00431                 success = listTables(&cmd[1], pattern, show_verbose, show_system);
00432                 break;
00433             case 'r':
00434                 if (cmd[2] == 'd' && cmd[3] == 's')
00435                 {
00436                     char       *pattern2 = NULL;
00437 
00438                     if (pattern)
00439                         pattern2 = psql_scan_slash_option(scan_state,
00440                                                       OT_NORMAL, NULL, true);
00441                     success = listDbRoleSettings(pattern, pattern2);
00442                 }
00443                 else
00444                     success = PSQL_CMD_UNKNOWN;
00445                 break;
00446             case 'u':
00447                 success = describeRoles(pattern, show_verbose);
00448                 break;
00449             case 'F':           /* text search subsystem */
00450                 switch (cmd[2])
00451                 {
00452                     case '\0':
00453                     case '+':
00454                         success = listTSConfigs(pattern, show_verbose);
00455                         break;
00456                     case 'p':
00457                         success = listTSParsers(pattern, show_verbose);
00458                         break;
00459                     case 'd':
00460                         success = listTSDictionaries(pattern, show_verbose);
00461                         break;
00462                     case 't':
00463                         success = listTSTemplates(pattern, show_verbose);
00464                         break;
00465                     default:
00466                         status = PSQL_CMD_UNKNOWN;
00467                         break;
00468                 }
00469                 break;
00470             case 'e':           /* SQL/MED subsystem */
00471                 switch (cmd[2])
00472                 {
00473                     case 's':
00474                         success = listForeignServers(pattern, show_verbose);
00475                         break;
00476                     case 'u':
00477                         success = listUserMappings(pattern, show_verbose);
00478                         break;
00479                     case 'w':
00480                         success = listForeignDataWrappers(pattern, show_verbose);
00481                         break;
00482                     case 't':
00483                         success = listForeignTables(pattern, show_verbose);
00484                         break;
00485                     default:
00486                         status = PSQL_CMD_UNKNOWN;
00487                         break;
00488                 }
00489                 break;
00490             case 'x':           /* Extensions */
00491                 if (show_verbose)
00492                     success = listExtensionContents(pattern);
00493                 else
00494                     success = listExtensions(pattern);
00495                 break;
00496             case 'y':           /* Event Triggers */
00497                 success = listEventTriggers(pattern, show_verbose);
00498                 break;
00499             default:
00500                 status = PSQL_CMD_UNKNOWN;
00501         }
00502 
00503         if (pattern)
00504             free(pattern);
00505     }
00506 
00507 
00508     /*
00509      * \e or \edit -- edit the current query buffer, or edit a file and make
00510      * it the query buffer
00511      */
00512     else if (strcmp(cmd, "e") == 0 || strcmp(cmd, "edit") == 0)
00513     {
00514         if (!query_buf)
00515         {
00516             psql_error("no query buffer\n");
00517             status = PSQL_CMD_ERROR;
00518         }
00519         else
00520         {
00521             char       *fname;
00522             char       *ln = NULL;
00523             int         lineno = -1;
00524 
00525             fname = psql_scan_slash_option(scan_state,
00526                                            OT_NORMAL, NULL, true);
00527             if (fname)
00528             {
00529                 /* try to get separate lineno arg */
00530                 ln = psql_scan_slash_option(scan_state,
00531                                             OT_NORMAL, NULL, true);
00532                 if (ln == NULL)
00533                 {
00534                     /* only one arg; maybe it is lineno not fname */
00535                     if (fname[0] &&
00536                         strspn(fname, "0123456789") == strlen(fname))
00537                     {
00538                         /* all digits, so assume it is lineno */
00539                         ln = fname;
00540                         fname = NULL;
00541                     }
00542                 }
00543             }
00544             if (ln)
00545             {
00546                 lineno = atoi(ln);
00547                 if (lineno < 1)
00548                 {
00549                     psql_error("invalid line number: %s\n", ln);
00550                     status = PSQL_CMD_ERROR;
00551                 }
00552             }
00553             if (status != PSQL_CMD_ERROR)
00554             {
00555                 expand_tilde(&fname);
00556                 if (fname)
00557                     canonicalize_path(fname);
00558                 if (do_edit(fname, query_buf, lineno, NULL))
00559                     status = PSQL_CMD_NEWEDIT;
00560                 else
00561                     status = PSQL_CMD_ERROR;
00562             }
00563             if (fname)
00564                 free(fname);
00565             if (ln)
00566                 free(ln);
00567         }
00568     }
00569 
00570     /*
00571      * \ef -- edit the named function, or present a blank CREATE FUNCTION
00572      * template if no argument is given
00573      */
00574     else if (strcmp(cmd, "ef") == 0)
00575     {
00576         int         lineno = -1;
00577 
00578         if (pset.sversion < 80400)
00579         {
00580             psql_error("The server (version %d.%d) does not support editing function source.\n",
00581                        pset.sversion / 10000, (pset.sversion / 100) % 100);
00582             status = PSQL_CMD_ERROR;
00583         }
00584         else if (!query_buf)
00585         {
00586             psql_error("no query buffer\n");
00587             status = PSQL_CMD_ERROR;
00588         }
00589         else
00590         {
00591             char       *func;
00592             Oid         foid = InvalidOid;
00593 
00594             func = psql_scan_slash_option(scan_state,
00595                                           OT_WHOLE_LINE, NULL, true);
00596             lineno = strip_lineno_from_funcdesc(func);
00597             if (lineno == 0)
00598             {
00599                 /* error already reported */
00600                 status = PSQL_CMD_ERROR;
00601             }
00602             else if (!func)
00603             {
00604                 /* set up an empty command to fill in */
00605                 printfPQExpBuffer(query_buf,
00606                                   "CREATE FUNCTION ( )\n"
00607                                   " RETURNS \n"
00608                                   " LANGUAGE \n"
00609                                   " -- common options:  IMMUTABLE  STABLE  STRICT  SECURITY DEFINER\n"
00610                                   "AS $function$\n"
00611                                   "\n$function$\n");
00612             }
00613             else if (!lookup_function_oid(pset.db, func, &foid))
00614             {
00615                 /* error already reported */
00616                 status = PSQL_CMD_ERROR;
00617             }
00618             else if (!get_create_function_cmd(pset.db, foid, query_buf))
00619             {
00620                 /* error already reported */
00621                 status = PSQL_CMD_ERROR;
00622             }
00623             else if (lineno > 0)
00624             {
00625                 /*
00626                  * lineno "1" should correspond to the first line of the
00627                  * function body.  We expect that pg_get_functiondef() will
00628                  * emit that on a line beginning with "AS ", and that there
00629                  * can be no such line before the real start of the function
00630                  * body.  Increment lineno by the number of lines before that
00631                  * line, so that it becomes relative to the first line of the
00632                  * function definition.
00633                  */
00634                 const char *lines = query_buf->data;
00635 
00636                 while (*lines != '\0')
00637                 {
00638                     if (strncmp(lines, "AS ", 3) == 0)
00639                         break;
00640                     lineno++;
00641                     /* find start of next line */
00642                     lines = strchr(lines, '\n');
00643                     if (!lines)
00644                         break;
00645                     lines++;
00646                 }
00647             }
00648 
00649             if (func)
00650                 free(func);
00651         }
00652 
00653         if (status != PSQL_CMD_ERROR)
00654         {
00655             bool        edited = false;
00656 
00657             if (!do_edit(NULL, query_buf, lineno, &edited))
00658                 status = PSQL_CMD_ERROR;
00659             else if (!edited)
00660                 puts(_("No changes"));
00661             else
00662                 status = PSQL_CMD_NEWEDIT;
00663         }
00664     }
00665 
00666     /* \echo and \qecho */
00667     else if (strcmp(cmd, "echo") == 0 || strcmp(cmd, "qecho") == 0)
00668     {
00669         char       *value;
00670         char        quoted;
00671         bool        no_newline = false;
00672         bool        first = true;
00673         FILE       *fout;
00674 
00675         if (strcmp(cmd, "qecho") == 0)
00676             fout = pset.queryFout;
00677         else
00678             fout = stdout;
00679 
00680         while ((value = psql_scan_slash_option(scan_state,
00681                                                OT_NORMAL, &quoted, false)))
00682         {
00683             if (!quoted && strcmp(value, "-n") == 0)
00684                 no_newline = true;
00685             else
00686             {
00687                 if (first)
00688                     first = false;
00689                 else
00690                     fputc(' ', fout);
00691                 fputs(value, fout);
00692             }
00693             free(value);
00694         }
00695         if (!no_newline)
00696             fputs("\n", fout);
00697     }
00698 
00699     /* \encoding -- set/show client side encoding */
00700     else if (strcmp(cmd, "encoding") == 0)
00701     {
00702         char       *encoding = psql_scan_slash_option(scan_state,
00703                                                       OT_NORMAL, NULL, false);
00704 
00705         if (!encoding)
00706         {
00707             /* show encoding */
00708             puts(pg_encoding_to_char(pset.encoding));
00709         }
00710         else
00711         {
00712             /* set encoding */
00713             if (PQsetClientEncoding(pset.db, encoding) == -1)
00714                 psql_error("%s: invalid encoding name or conversion procedure not found\n", encoding);
00715             else
00716             {
00717                 /* save encoding info into psql internal data */
00718                 pset.encoding = PQclientEncoding(pset.db);
00719                 pset.popt.topt.encoding = pset.encoding;
00720                 SetVariable(pset.vars, "ENCODING",
00721                             pg_encoding_to_char(pset.encoding));
00722             }
00723             free(encoding);
00724         }
00725     }
00726 
00727     /* \f -- change field separator */
00728     else if (strcmp(cmd, "f") == 0)
00729     {
00730         char       *fname = psql_scan_slash_option(scan_state,
00731                                                    OT_NORMAL, NULL, false);
00732 
00733         success = do_pset("fieldsep", fname, &pset.popt, pset.quiet);
00734         free(fname);
00735     }
00736 
00737     /* \g [filename] -- send query, optionally with output to file/pipe */
00738     else if (strcmp(cmd, "g") == 0)
00739     {
00740         char       *fname = psql_scan_slash_option(scan_state,
00741                                                    OT_FILEPIPE, NULL, false);
00742 
00743         if (!fname)
00744             pset.gfname = NULL;
00745         else
00746         {
00747             expand_tilde(&fname);
00748             pset.gfname = pg_strdup(fname);
00749         }
00750         free(fname);
00751         status = PSQL_CMD_SEND;
00752     }
00753 
00754     /* \gset [prefix] -- send query and store result into variables */
00755     else if (strcmp(cmd, "gset") == 0)
00756     {
00757         char       *prefix = psql_scan_slash_option(scan_state,
00758                                                     OT_NORMAL, NULL, false);
00759 
00760         if (prefix)
00761             pset.gset_prefix = prefix;
00762         else
00763         {
00764             /* we must set a non-NULL prefix to trigger storing */
00765             pset.gset_prefix = pg_strdup("");
00766         }
00767         status = PSQL_CMD_SEND;
00768     }
00769 
00770     /* help */
00771     else if (strcmp(cmd, "h") == 0 || strcmp(cmd, "help") == 0)
00772     {
00773         char       *opt = psql_scan_slash_option(scan_state,
00774                                                  OT_WHOLE_LINE, NULL, false);
00775         size_t      len;
00776 
00777         /* strip any trailing spaces and semicolons */
00778         if (opt)
00779         {
00780             len = strlen(opt);
00781             while (len > 0 &&
00782                    (isspace((unsigned char) opt[len - 1])
00783                     || opt[len - 1] == ';'))
00784                 opt[--len] = '\0';
00785         }
00786 
00787         helpSQL(opt, pset.popt.topt.pager);
00788         free(opt);
00789     }
00790 
00791     /* HTML mode */
00792     else if (strcmp(cmd, "H") == 0 || strcmp(cmd, "html") == 0)
00793     {
00794         if (pset.popt.topt.format != PRINT_HTML)
00795             success = do_pset("format", "html", &pset.popt, pset.quiet);
00796         else
00797             success = do_pset("format", "aligned", &pset.popt, pset.quiet);
00798     }
00799 
00800 
00801     /* \i and \ir include files */
00802     else if (strcmp(cmd, "i") == 0 || strcmp(cmd, "include") == 0
00803            || strcmp(cmd, "ir") == 0 || strcmp(cmd, "include_relative") == 0)
00804     {
00805         char       *fname = psql_scan_slash_option(scan_state,
00806                                                    OT_NORMAL, NULL, true);
00807 
00808         if (!fname)
00809         {
00810             psql_error("\\%s: missing required argument\n", cmd);
00811             success = false;
00812         }
00813         else
00814         {
00815             bool        include_relative;
00816 
00817             include_relative = (strcmp(cmd, "ir") == 0
00818                                 || strcmp(cmd, "include_relative") == 0);
00819             expand_tilde(&fname);
00820             success = (process_file(fname, false, include_relative) == EXIT_SUCCESS);
00821             free(fname);
00822         }
00823     }
00824 
00825     /* \l is list databases */
00826     else if (strcmp(cmd, "l") == 0 || strcmp(cmd, "list") == 0 ||
00827              strcmp(cmd, "l+") == 0 || strcmp(cmd, "list+") == 0)
00828     {
00829         char       *pattern;
00830         bool        show_verbose;
00831 
00832         pattern = psql_scan_slash_option(scan_state,
00833                                          OT_NORMAL, NULL, true);
00834 
00835         show_verbose = strchr(cmd, '+') ? true : false;
00836 
00837         success = listAllDbs(pattern, show_verbose);
00838 
00839         if (pattern)
00840             free(pattern);
00841     }
00842 
00843     /*
00844      * large object things
00845      */
00846     else if (strncmp(cmd, "lo_", 3) == 0)
00847     {
00848         char       *opt1,
00849                    *opt2;
00850 
00851         opt1 = psql_scan_slash_option(scan_state,
00852                                       OT_NORMAL, NULL, true);
00853         opt2 = psql_scan_slash_option(scan_state,
00854                                       OT_NORMAL, NULL, true);
00855 
00856         if (strcmp(cmd + 3, "export") == 0)
00857         {
00858             if (!opt2)
00859             {
00860                 psql_error("\\%s: missing required argument\n", cmd);
00861                 success = false;
00862             }
00863             else
00864             {
00865                 expand_tilde(&opt2);
00866                 success = do_lo_export(opt1, opt2);
00867             }
00868         }
00869 
00870         else if (strcmp(cmd + 3, "import") == 0)
00871         {
00872             if (!opt1)
00873             {
00874                 psql_error("\\%s: missing required argument\n", cmd);
00875                 success = false;
00876             }
00877             else
00878             {
00879                 expand_tilde(&opt1);
00880                 success = do_lo_import(opt1, opt2);
00881             }
00882         }
00883 
00884         else if (strcmp(cmd + 3, "list") == 0)
00885             success = do_lo_list();
00886 
00887         else if (strcmp(cmd + 3, "unlink") == 0)
00888         {
00889             if (!opt1)
00890             {
00891                 psql_error("\\%s: missing required argument\n", cmd);
00892                 success = false;
00893             }
00894             else
00895                 success = do_lo_unlink(opt1);
00896         }
00897 
00898         else
00899             status = PSQL_CMD_UNKNOWN;
00900 
00901         free(opt1);
00902         free(opt2);
00903     }
00904 
00905 
00906     /* \o -- set query output */
00907     else if (strcmp(cmd, "o") == 0 || strcmp(cmd, "out") == 0)
00908     {
00909         char       *fname = psql_scan_slash_option(scan_state,
00910                                                    OT_FILEPIPE, NULL, true);
00911 
00912         expand_tilde(&fname);
00913         success = setQFout(fname);
00914         free(fname);
00915     }
00916 
00917     /* \p prints the current query buffer */
00918     else if (strcmp(cmd, "p") == 0 || strcmp(cmd, "print") == 0)
00919     {
00920         if (query_buf && query_buf->len > 0)
00921             puts(query_buf->data);
00922         else if (!pset.quiet)
00923             puts(_("Query buffer is empty."));
00924         fflush(stdout);
00925     }
00926 
00927     /* \password -- set user password */
00928     else if (strcmp(cmd, "password") == 0)
00929     {
00930         char       *pw1;
00931         char       *pw2;
00932 
00933         pw1 = simple_prompt("Enter new password: ", 100, false);
00934         pw2 = simple_prompt("Enter it again: ", 100, false);
00935 
00936         if (strcmp(pw1, pw2) != 0)
00937         {
00938             psql_error("Passwords didn't match.\n");
00939             success = false;
00940         }
00941         else
00942         {
00943             char       *opt0 = psql_scan_slash_option(scan_state, OT_SQLID, NULL, true);
00944             char       *user;
00945             char       *encrypted_password;
00946 
00947             if (opt0)
00948                 user = opt0;
00949             else
00950                 user = PQuser(pset.db);
00951 
00952             encrypted_password = PQencryptPassword(pw1, user);
00953 
00954             if (!encrypted_password)
00955             {
00956                 psql_error("Password encryption failed.\n");
00957                 success = false;
00958             }
00959             else
00960             {
00961                 PQExpBufferData buf;
00962                 PGresult   *res;
00963 
00964                 initPQExpBuffer(&buf);
00965                 printfPQExpBuffer(&buf, "ALTER USER %s PASSWORD ",
00966                                   fmtId(user));
00967                 appendStringLiteralConn(&buf, encrypted_password, pset.db);
00968                 res = PSQLexec(buf.data, false);
00969                 termPQExpBuffer(&buf);
00970                 if (!res)
00971                     success = false;
00972                 else
00973                     PQclear(res);
00974                 PQfreemem(encrypted_password);
00975             }
00976 
00977             if (opt0)
00978                 free(opt0);
00979         }
00980 
00981         free(pw1);
00982         free(pw2);
00983     }
00984 
00985     /* \prompt -- prompt and set variable */
00986     else if (strcmp(cmd, "prompt") == 0)
00987     {
00988         char       *opt,
00989                    *prompt_text = NULL;
00990         char       *arg1,
00991                    *arg2;
00992 
00993         arg1 = psql_scan_slash_option(scan_state, OT_NORMAL, NULL, false);
00994         arg2 = psql_scan_slash_option(scan_state, OT_NORMAL, NULL, false);
00995 
00996         if (!arg1)
00997         {
00998             psql_error("\\%s: missing required argument\n", cmd);
00999             success = false;
01000         }
01001         else
01002         {
01003             char       *result;
01004 
01005             if (arg2)
01006             {
01007                 prompt_text = arg1;
01008                 opt = arg2;
01009             }
01010             else
01011                 opt = arg1;
01012 
01013             if (!pset.inputfile)
01014                 result = simple_prompt(prompt_text, 4096, true);
01015             else
01016             {
01017                 if (prompt_text)
01018                 {
01019                     fputs(prompt_text, stdout);
01020                     fflush(stdout);
01021                 }
01022                 result = gets_fromFile(stdin);
01023             }
01024 
01025             if (!SetVariable(pset.vars, opt, result))
01026             {
01027                 psql_error("\\%s: error while setting variable\n", cmd);
01028                 success = false;
01029             }
01030 
01031             free(result);
01032             if (prompt_text)
01033                 free(prompt_text);
01034             free(opt);
01035         }
01036     }
01037 
01038     /* \pset -- set printing parameters */
01039     else if (strcmp(cmd, "pset") == 0)
01040     {
01041         char       *opt0 = psql_scan_slash_option(scan_state,
01042                                                   OT_NORMAL, NULL, false);
01043         char       *opt1 = psql_scan_slash_option(scan_state,
01044                                                   OT_NORMAL, NULL, false);
01045 
01046         if (!opt0)
01047         {
01048             psql_error("\\%s: missing required argument\n", cmd);
01049             success = false;
01050         }
01051         else
01052             success = do_pset(opt0, opt1, &pset.popt, pset.quiet);
01053 
01054         free(opt0);
01055         free(opt1);
01056     }
01057 
01058     /* \q or \quit */
01059     else if (strcmp(cmd, "q") == 0 || strcmp(cmd, "quit") == 0)
01060         status = PSQL_CMD_TERMINATE;
01061 
01062     /* reset(clear) the buffer */
01063     else if (strcmp(cmd, "r") == 0 || strcmp(cmd, "reset") == 0)
01064     {
01065         resetPQExpBuffer(query_buf);
01066         psql_scan_reset(scan_state);
01067         if (!pset.quiet)
01068             puts(_("Query buffer reset (cleared)."));
01069     }
01070 
01071     /* \s save history in a file or show it on the screen */
01072     else if (strcmp(cmd, "s") == 0)
01073     {
01074         char       *fname = psql_scan_slash_option(scan_state,
01075                                                    OT_NORMAL, NULL, true);
01076 
01077 #if defined(WIN32) && !defined(__CYGWIN__)
01078 
01079         /*
01080          * XXX This does not work for all terminal environments or for output
01081          * containing non-ASCII characters; see comments in simple_prompt().
01082          */
01083 #define DEVTTY  "con"
01084 #else
01085 #define DEVTTY  "/dev/tty"
01086 #endif
01087 
01088         expand_tilde(&fname);
01089         /* This scrolls off the screen when using /dev/tty */
01090         success = saveHistory(fname ? fname : DEVTTY, -1, false, false);
01091         if (success && !pset.quiet && fname)
01092             printf(gettext("Wrote history to file \"%s/%s\".\n"),
01093                    pset.dirname ? pset.dirname : ".", fname);
01094         if (!fname)
01095             putchar('\n');
01096         free(fname);
01097     }
01098 
01099     /* \set -- generalized set variable/option command */
01100     else if (strcmp(cmd, "set") == 0)
01101     {
01102         char       *opt0 = psql_scan_slash_option(scan_state,
01103                                                   OT_NORMAL, NULL, false);
01104 
01105         if (!opt0)
01106         {
01107             /* list all variables */
01108             PrintVariables(pset.vars);
01109             success = true;
01110         }
01111         else
01112         {
01113             /*
01114              * Set variable to the concatenation of the arguments.
01115              */
01116             char       *newval;
01117             char       *opt;
01118 
01119             opt = psql_scan_slash_option(scan_state,
01120                                          OT_NORMAL, NULL, false);
01121             newval = pg_strdup(opt ? opt : "");
01122             free(opt);
01123 
01124             while ((opt = psql_scan_slash_option(scan_state,
01125                                                  OT_NORMAL, NULL, false)))
01126             {
01127                 newval = realloc(newval, strlen(newval) + strlen(opt) + 1);
01128                 if (!newval)
01129                 {
01130                     psql_error("out of memory\n");
01131                     exit(EXIT_FAILURE);
01132                 }
01133                 strcat(newval, opt);
01134                 free(opt);
01135             }
01136 
01137             if (!SetVariable(pset.vars, opt0, newval))
01138             {
01139                 psql_error("\\%s: error while setting variable\n", cmd);
01140                 success = false;
01141             }
01142             free(newval);
01143         }
01144         free(opt0);
01145     }
01146 
01147 
01148     /* \setenv -- set environment command */
01149     else if (strcmp(cmd, "setenv") == 0)
01150     {
01151         char       *envvar = psql_scan_slash_option(scan_state,
01152                                                     OT_NORMAL, NULL, false);
01153         char       *envval = psql_scan_slash_option(scan_state,
01154                                                     OT_NORMAL, NULL, false);
01155 
01156         if (!envvar)
01157         {
01158             psql_error("\\%s: missing required argument\n", cmd);
01159             success = false;
01160         }
01161         else if (strchr(envvar, '=') != NULL)
01162         {
01163             psql_error("\\%s: environment variable name must not contain \"=\"\n",
01164                        cmd);
01165             success = false;
01166         }
01167         else if (!envval)
01168         {
01169             /* No argument - unset the environment variable */
01170             unsetenv(envvar);
01171             success = true;
01172         }
01173         else
01174         {
01175             /* Set variable to the value of the next argument */
01176             int         len = strlen(envvar) + strlen(envval) + 1;
01177             char       *newval = pg_malloc(len + 1);
01178 
01179             snprintf(newval, len + 1, "%s=%s", envvar, envval);
01180             putenv(newval);
01181             success = true;
01182 
01183             /*
01184              * Do not free newval here, it will screw up the environment if
01185              * you do. See putenv man page for details. That means we leak a
01186              * bit of memory here, but not enough to worry about.
01187              */
01188         }
01189         free(envvar);
01190         free(envval);
01191     }
01192 
01193     /* \sf -- show a function's source code */
01194     else if (strcmp(cmd, "sf") == 0 || strcmp(cmd, "sf+") == 0)
01195     {
01196         bool        show_linenumbers = (strcmp(cmd, "sf+") == 0);
01197         PQExpBuffer func_buf;
01198         char       *func;
01199         Oid         foid = InvalidOid;
01200 
01201         func_buf = createPQExpBuffer();
01202         func = psql_scan_slash_option(scan_state,
01203                                       OT_WHOLE_LINE, NULL, true);
01204         if (pset.sversion < 80400)
01205         {
01206             psql_error("The server (version %d.%d) does not support showing function source.\n",
01207                        pset.sversion / 10000, (pset.sversion / 100) % 100);
01208             status = PSQL_CMD_ERROR;
01209         }
01210         else if (!func)
01211         {
01212             psql_error("function name is required\n");
01213             status = PSQL_CMD_ERROR;
01214         }
01215         else if (!lookup_function_oid(pset.db, func, &foid))
01216         {
01217             /* error already reported */
01218             status = PSQL_CMD_ERROR;
01219         }
01220         else if (!get_create_function_cmd(pset.db, foid, func_buf))
01221         {
01222             /* error already reported */
01223             status = PSQL_CMD_ERROR;
01224         }
01225         else
01226         {
01227             FILE       *output;
01228             bool        is_pager;
01229 
01230             /* Select output stream: stdout, pager, or file */
01231             if (pset.queryFout == stdout)
01232             {
01233                 /* count lines in function to see if pager is needed */
01234                 int         lineno = 0;
01235                 const char *lines = func_buf->data;
01236 
01237                 while (*lines != '\0')
01238                 {
01239                     lineno++;
01240                     /* find start of next line */
01241                     lines = strchr(lines, '\n');
01242                     if (!lines)
01243                         break;
01244                     lines++;
01245                 }
01246 
01247                 output = PageOutput(lineno, pset.popt.topt.pager);
01248                 is_pager = true;
01249             }
01250             else
01251             {
01252                 /* use previously set output file, without pager */
01253                 output = pset.queryFout;
01254                 is_pager = false;
01255             }
01256 
01257             if (show_linenumbers)
01258             {
01259                 bool        in_header = true;
01260                 int         lineno = 0;
01261                 char       *lines = func_buf->data;
01262 
01263                 /*
01264                  * lineno "1" should correspond to the first line of the
01265                  * function body.  We expect that pg_get_functiondef() will
01266                  * emit that on a line beginning with "AS ", and that there
01267                  * can be no such line before the real start of the function
01268                  * body.
01269                  *
01270                  * Note that this loop scribbles on func_buf.
01271                  */
01272                 while (*lines != '\0')
01273                 {
01274                     char       *eol;
01275 
01276                     if (in_header && strncmp(lines, "AS ", 3) == 0)
01277                         in_header = false;
01278                     /* increment lineno only for body's lines */
01279                     if (!in_header)
01280                         lineno++;
01281 
01282                     /* find and mark end of current line */
01283                     eol = strchr(lines, '\n');
01284                     if (eol != NULL)
01285                         *eol = '\0';
01286 
01287                     /* show current line as appropriate */
01288                     if (in_header)
01289                         fprintf(output, "        %s\n", lines);
01290                     else
01291                         fprintf(output, "%-7d %s\n", lineno, lines);
01292 
01293                     /* advance to next line, if any */
01294                     if (eol == NULL)
01295                         break;
01296                     lines = ++eol;
01297                 }
01298             }
01299             else
01300             {
01301                 /* just send the function definition to output */
01302                 fputs(func_buf->data, output);
01303             }
01304 
01305             if (is_pager)
01306                 ClosePager(output);
01307         }
01308 
01309         if (func)
01310             free(func);
01311         destroyPQExpBuffer(func_buf);
01312     }
01313 
01314     /* \t -- turn off headers and row count */
01315     else if (strcmp(cmd, "t") == 0)
01316     {
01317         char       *opt = psql_scan_slash_option(scan_state,
01318                                                  OT_NORMAL, NULL, true);
01319 
01320         success = do_pset("tuples_only", opt, &pset.popt, pset.quiet);
01321         free(opt);
01322     }
01323 
01324     /* \T -- define html <table ...> attributes */
01325     else if (strcmp(cmd, "T") == 0)
01326     {
01327         char       *value = psql_scan_slash_option(scan_state,
01328                                                    OT_NORMAL, NULL, false);
01329 
01330         success = do_pset("tableattr", value, &pset.popt, pset.quiet);
01331         free(value);
01332     }
01333 
01334     /* \timing -- toggle timing of queries */
01335     else if (strcmp(cmd, "timing") == 0)
01336     {
01337         char       *opt = psql_scan_slash_option(scan_state,
01338                                                  OT_NORMAL, NULL, false);
01339 
01340         if (opt)
01341             pset.timing = ParseVariableBool(opt);
01342         else
01343             pset.timing = !pset.timing;
01344         if (!pset.quiet)
01345         {
01346             if (pset.timing)
01347                 puts(_("Timing is on."));
01348             else
01349                 puts(_("Timing is off."));
01350         }
01351         free(opt);
01352     }
01353 
01354     /* \unset */
01355     else if (strcmp(cmd, "unset") == 0)
01356     {
01357         char       *opt = psql_scan_slash_option(scan_state,
01358                                                  OT_NORMAL, NULL, false);
01359 
01360         if (!opt)
01361         {
01362             psql_error("\\%s: missing required argument\n", cmd);
01363             success = false;
01364         }
01365         else if (!SetVariable(pset.vars, opt, NULL))
01366         {
01367             psql_error("\\%s: error while setting variable\n", cmd);
01368             success = false;
01369         }
01370         free(opt);
01371     }
01372 
01373     /* \w -- write query buffer to file */
01374     else if (strcmp(cmd, "w") == 0 || strcmp(cmd, "write") == 0)
01375     {
01376         FILE       *fd = NULL;
01377         bool        is_pipe = false;
01378         char       *fname = NULL;
01379 
01380         if (!query_buf)
01381         {
01382             psql_error("no query buffer\n");
01383             status = PSQL_CMD_ERROR;
01384         }
01385         else
01386         {
01387             fname = psql_scan_slash_option(scan_state,
01388                                            OT_FILEPIPE, NULL, true);
01389             expand_tilde(&fname);
01390 
01391             if (!fname)
01392             {
01393                 psql_error("\\%s: missing required argument\n", cmd);
01394                 success = false;
01395             }
01396             else
01397             {
01398                 if (fname[0] == '|')
01399                 {
01400                     is_pipe = true;
01401                     fd = popen(&fname[1], "w");
01402                 }
01403                 else
01404                 {
01405                     canonicalize_path(fname);
01406                     fd = fopen(fname, "w");
01407                 }
01408                 if (!fd)
01409                 {
01410                     psql_error("%s: %s\n", fname, strerror(errno));
01411                     success = false;
01412                 }
01413             }
01414         }
01415 
01416         if (fd)
01417         {
01418             int         result;
01419 
01420             if (query_buf && query_buf->len > 0)
01421                 fprintf(fd, "%s\n", query_buf->data);
01422 
01423             if (is_pipe)
01424                 result = pclose(fd);
01425             else
01426                 result = fclose(fd);
01427 
01428             if (result == EOF)
01429             {
01430                 psql_error("%s: %s\n", fname, strerror(errno));
01431                 success = false;
01432             }
01433         }
01434 
01435         free(fname);
01436     }
01437 
01438     /* \watch -- execute a query every N seconds */
01439     else if (strcmp(cmd, "watch") == 0)
01440     {
01441         char       *opt = psql_scan_slash_option(scan_state,
01442                                                  OT_NORMAL, NULL, true);
01443         long        sleep = 2;
01444 
01445         /* Convert optional sleep-length argument */
01446         if (opt)
01447         {
01448             sleep = strtol(opt, NULL, 10);
01449             if (sleep <= 0)
01450                 sleep = 1;
01451             free(opt);
01452         }
01453 
01454         success = do_watch(query_buf, sleep);
01455 
01456         /* Reset the query buffer as though for \r */
01457         resetPQExpBuffer(query_buf);
01458         psql_scan_reset(scan_state);
01459     }
01460 
01461     /* \x -- set or toggle expanded table representation */
01462     else if (strcmp(cmd, "x") == 0)
01463     {
01464         char       *opt = psql_scan_slash_option(scan_state,
01465                                                  OT_NORMAL, NULL, true);
01466 
01467         success = do_pset("expanded", opt, &pset.popt, pset.quiet);
01468         free(opt);
01469     }
01470 
01471     /* \z -- list table rights (equivalent to \dp) */
01472     else if (strcmp(cmd, "z") == 0)
01473     {
01474         char       *pattern = psql_scan_slash_option(scan_state,
01475                                                      OT_NORMAL, NULL, true);
01476 
01477         success = permissionsList(pattern);
01478         if (pattern)
01479             free(pattern);
01480     }
01481 
01482     /* \! -- shell escape */
01483     else if (strcmp(cmd, "!") == 0)
01484     {
01485         char       *opt = psql_scan_slash_option(scan_state,
01486                                                  OT_WHOLE_LINE, NULL, false);
01487 
01488         success = do_shell(opt);
01489         free(opt);
01490     }
01491 
01492     /* \? -- slash command help */
01493     else if (strcmp(cmd, "?") == 0)
01494         slashUsage(pset.popt.topt.pager);
01495 
01496 #if 0
01497 
01498     /*
01499      * These commands don't do anything. I just use them to test the parser.
01500      */
01501     else if (strcmp(cmd, "void") == 0 || strcmp(cmd, "#") == 0)
01502     {
01503         int         i = 0;
01504         char       *value;
01505 
01506         while ((value = psql_scan_slash_option(scan_state,
01507                                                OT_NORMAL, NULL, true)))
01508         {
01509             psql_error("+ opt(%d) = |%s|\n", i++, value);
01510             free(value);
01511         }
01512     }
01513 #endif
01514 
01515     else
01516         status = PSQL_CMD_UNKNOWN;
01517 
01518     if (!success)
01519         status = PSQL_CMD_ERROR;
01520 
01521     return status;
01522 }
01523 
01524 /*
01525  * Ask the user for a password; 'username' is the username the
01526  * password is for, if one has been explicitly specified. Returns a
01527  * malloc'd string.
01528  */
01529 static char *
01530 prompt_for_password(const char *username)
01531 {
01532     char       *result;
01533 
01534     if (username == NULL)
01535         result = simple_prompt("Password: ", 100, false);
01536     else
01537     {
01538         char       *prompt_text;
01539 
01540         prompt_text = pg_malloc(strlen(username) + 100);
01541         snprintf(prompt_text, strlen(username) + 100,
01542                  _("Password for user %s: "), username);
01543         result = simple_prompt(prompt_text, 100, false);
01544         free(prompt_text);
01545     }
01546 
01547     return result;
01548 }
01549 
01550 static bool
01551 param_is_newly_set(const char *old_val, const char *new_val)
01552 {
01553     if (new_val == NULL)
01554         return false;
01555 
01556     if (old_val == NULL || strcmp(old_val, new_val) != 0)
01557         return true;
01558 
01559     return false;
01560 }
01561 
01562 /*
01563  * do_connect -- handler for \connect
01564  *
01565  * Connects to a database with given parameters. If there exists an
01566  * established connection, NULL values will be replaced with the ones
01567  * in the current connection. Otherwise NULL will be passed for that
01568  * parameter to PQconnectdbParams(), so the libpq defaults will be used.
01569  *
01570  * In interactive mode, if connection fails with the given parameters,
01571  * the old connection will be kept.
01572  */
01573 static bool
01574 do_connect(char *dbname, char *user, char *host, char *port)
01575 {
01576     PGconn     *o_conn = pset.db,
01577                *n_conn;
01578     char       *password = NULL;
01579 
01580     if (!o_conn && (!dbname || !user || !host || !port))
01581     {
01582         /*
01583          *  We don't know the supplied connection parameters and don't want
01584          *  to connect to the wrong database by using defaults, so require
01585          *  all parameters to be specified.
01586          */
01587         psql_error("All connection parameters must be supplied because no "
01588                    "database connection exists\n");
01589         return false;
01590     }
01591 
01592     if (!dbname)
01593         dbname = PQdb(o_conn);
01594     if (!user)
01595         user = PQuser(o_conn);
01596     if (!host)
01597         host = PQhost(o_conn);
01598     if (!port)
01599         port = PQport(o_conn);
01600 
01601     /*
01602      * If the user asked to be prompted for a password, ask for one now. If
01603      * not, use the password from the old connection, provided the username
01604      * has not changed. Otherwise, try to connect without a password first,
01605      * and then ask for a password if needed.
01606      *
01607      * XXX: this behavior leads to spurious connection attempts recorded in
01608      * the postmaster's log.  But libpq offers no API that would let us obtain
01609      * a password and then continue with the first connection attempt.
01610      */
01611     if (pset.getPassword == TRI_YES)
01612     {
01613         password = prompt_for_password(user);
01614     }
01615     else if (o_conn && user && strcmp(PQuser(o_conn), user) == 0)
01616     {
01617         password = pg_strdup(PQpass(o_conn));
01618     }
01619 
01620     while (true)
01621     {
01622 #define PARAMS_ARRAY_SIZE   8
01623         const char **keywords = pg_malloc(PARAMS_ARRAY_SIZE * sizeof(*keywords));
01624         const char **values = pg_malloc(PARAMS_ARRAY_SIZE * sizeof(*values));
01625 
01626         keywords[0] = "host";
01627         values[0] = host;
01628         keywords[1] = "port";
01629         values[1] = port;
01630         keywords[2] = "user";
01631         values[2] = user;
01632         keywords[3] = "password";
01633         values[3] = password;
01634         keywords[4] = "dbname";
01635         values[4] = dbname;
01636         keywords[5] = "fallback_application_name";
01637         values[5] = pset.progname;
01638         keywords[6] = "client_encoding";
01639         values[6] = (pset.notty || getenv("PGCLIENTENCODING")) ? NULL : "auto";
01640         keywords[7] = NULL;
01641         values[7] = NULL;
01642 
01643         n_conn = PQconnectdbParams(keywords, values, true);
01644 
01645         free(keywords);
01646         free(values);
01647 
01648         /* We can immediately discard the password -- no longer needed */
01649         if (password)
01650             free(password);
01651 
01652         if (PQstatus(n_conn) == CONNECTION_OK)
01653             break;
01654 
01655         /*
01656          * Connection attempt failed; either retry the connection attempt with
01657          * a new password, or give up.
01658          */
01659         if (!password && PQconnectionNeedsPassword(n_conn) && pset.getPassword != TRI_NO)
01660         {
01661             PQfinish(n_conn);
01662             password = prompt_for_password(user);
01663             continue;
01664         }
01665 
01666         /*
01667          * Failed to connect to the database. In interactive mode, keep the
01668          * previous connection to the DB; in scripting mode, close our
01669          * previous connection as well.
01670          */
01671         if (pset.cur_cmd_interactive)
01672         {
01673             psql_error("%s", PQerrorMessage(n_conn));
01674 
01675             /* pset.db is left unmodified */
01676             if (o_conn)
01677                 psql_error("Previous connection kept\n");
01678         }
01679         else
01680         {
01681             psql_error("\\connect: %s", PQerrorMessage(n_conn));
01682             if (o_conn)
01683             {
01684                 PQfinish(o_conn);
01685                 pset.db = NULL;
01686             }
01687         }
01688 
01689         PQfinish(n_conn);
01690         return false;
01691     }
01692 
01693     /*
01694      * Replace the old connection with the new one, and update
01695      * connection-dependent variables.
01696      */
01697     PQsetNoticeProcessor(n_conn, NoticeProcessor, NULL);
01698     pset.db = n_conn;
01699     SyncVariables();
01700     connection_warnings(false); /* Must be after SyncVariables */
01701 
01702     /* Tell the user about the new connection */
01703     if (!pset.quiet)
01704     {
01705         if (param_is_newly_set(PQhost(o_conn), PQhost(pset.db)) ||
01706             param_is_newly_set(PQport(o_conn), PQport(pset.db)))
01707         {
01708             char       *host = PQhost(pset.db);
01709 
01710             if (host == NULL)
01711                 host = DEFAULT_PGSOCKET_DIR;
01712             /* If the host is an absolute path, the connection is via socket */
01713             if (is_absolute_path(host))
01714                 printf(_("You are now connected to database \"%s\" as user \"%s\" via socket in \"%s\" at port \"%s\".\n"),
01715                        PQdb(pset.db), PQuser(pset.db), host, PQport(pset.db));
01716             else
01717                 printf(_("You are now connected to database \"%s\" as user \"%s\" on host \"%s\" at port \"%s\".\n"),
01718                        PQdb(pset.db), PQuser(pset.db), host, PQport(pset.db));
01719         }
01720         else
01721             printf(_("You are now connected to database \"%s\" as user \"%s\".\n"),
01722                    PQdb(pset.db), PQuser(pset.db));
01723     }
01724 
01725     if (o_conn)
01726         PQfinish(o_conn);
01727     return true;
01728 }
01729 
01730 
01731 void
01732 connection_warnings(bool in_startup)
01733 {
01734     if (!pset.quiet && !pset.notty)
01735     {
01736         int         client_ver = PG_VERSION_NUM;
01737 
01738         if (pset.sversion != client_ver)
01739         {
01740             const char *server_version;
01741             char        server_ver_str[16];
01742 
01743             /* Try to get full text form, might include "devel" etc */
01744             server_version = PQparameterStatus(pset.db, "server_version");
01745             if (!server_version)
01746             {
01747                 snprintf(server_ver_str, sizeof(server_ver_str),
01748                          "%d.%d.%d",
01749                          pset.sversion / 10000,
01750                          (pset.sversion / 100) % 100,
01751                          pset.sversion % 100);
01752                 server_version = server_ver_str;
01753             }
01754 
01755             printf(_("%s (%s, server %s)\n"),
01756                    pset.progname, PG_VERSION, server_version);
01757         }
01758         /* For version match, only print psql banner on startup. */
01759         else if (in_startup)
01760             printf("%s (%s)\n", pset.progname, PG_VERSION);
01761 
01762         if (pset.sversion / 100 > client_ver / 100)
01763             printf(_("WARNING: %s major version %d.%d, server major version %d.%d.\n"
01764                      "         Some psql features might not work.\n"),
01765                  pset.progname, client_ver / 10000, (client_ver / 100) % 100,
01766                    pset.sversion / 10000, (pset.sversion / 100) % 100);
01767 
01768 #ifdef WIN32
01769         checkWin32Codepage();
01770 #endif
01771         printSSLInfo();
01772     }
01773 }
01774 
01775 
01776 /*
01777  * printSSLInfo
01778  *
01779  * Prints information about the current SSL connection, if SSL is in use
01780  */
01781 static void
01782 printSSLInfo(void)
01783 {
01784 #ifdef USE_SSL
01785     int         sslbits = -1;
01786     SSL        *ssl;
01787 
01788     ssl = PQgetssl(pset.db);
01789     if (!ssl)
01790         return;                 /* no SSL */
01791 
01792     SSL_get_cipher_bits(ssl, &sslbits);
01793     printf(_("SSL connection (cipher: %s, bits: %d)\n"),
01794            SSL_get_cipher(ssl), sslbits);
01795 #else
01796 
01797     /*
01798      * If psql is compiled without SSL but is using a libpq with SSL, we
01799      * cannot figure out the specifics about the connection. But we know it's
01800      * SSL secured.
01801      */
01802     if (PQgetssl(pset.db))
01803         printf(_("SSL connection (unknown cipher)\n"));
01804 #endif
01805 }
01806 
01807 
01808 /*
01809  * checkWin32Codepage
01810  *
01811  * Prints a warning when win32 console codepage differs from Windows codepage
01812  */
01813 #ifdef WIN32
01814 static void
01815 checkWin32Codepage(void)
01816 {
01817     unsigned int wincp,
01818                 concp;
01819 
01820     wincp = GetACP();
01821     concp = GetConsoleCP();
01822     if (wincp != concp)
01823     {
01824         printf(_("WARNING: Console code page (%u) differs from Windows code page (%u)\n"
01825                  "         8-bit characters might not work correctly. See psql reference\n"
01826                  "         page \"Notes for Windows users\" for details.\n"),
01827                concp, wincp);
01828     }
01829 }
01830 #endif
01831 
01832 
01833 /*
01834  * SyncVariables
01835  *
01836  * Make psql's internal variables agree with connection state upon
01837  * establishing a new connection.
01838  */
01839 void
01840 SyncVariables(void)
01841 {
01842     /* get stuff from connection */
01843     pset.encoding = PQclientEncoding(pset.db);
01844     pset.popt.topt.encoding = pset.encoding;
01845     pset.sversion = PQserverVersion(pset.db);
01846 
01847     SetVariable(pset.vars, "DBNAME", PQdb(pset.db));
01848     SetVariable(pset.vars, "USER", PQuser(pset.db));
01849     SetVariable(pset.vars, "HOST", PQhost(pset.db));
01850     SetVariable(pset.vars, "PORT", PQport(pset.db));
01851     SetVariable(pset.vars, "ENCODING", pg_encoding_to_char(pset.encoding));
01852 
01853     /* send stuff to it, too */
01854     PQsetErrorVerbosity(pset.db, pset.verbosity);
01855 }
01856 
01857 /*
01858  * UnsyncVariables
01859  *
01860  * Clear variables that should be not be set when there is no connection.
01861  */
01862 void
01863 UnsyncVariables(void)
01864 {
01865     SetVariable(pset.vars, "DBNAME", NULL);
01866     SetVariable(pset.vars, "USER", NULL);
01867     SetVariable(pset.vars, "HOST", NULL);
01868     SetVariable(pset.vars, "PORT", NULL);
01869     SetVariable(pset.vars, "ENCODING", NULL);
01870 }
01871 
01872 
01873 /*
01874  * do_edit -- handler for \e
01875  *
01876  * If you do not specify a filename, the current query buffer will be copied
01877  * into a temporary one.
01878  */
01879 static bool
01880 editFile(const char *fname, int lineno)
01881 {
01882     const char *editorName;
01883     const char *editor_lineno_arg = NULL;
01884     char       *sys;
01885     int         result;
01886 
01887     Assert(fname != NULL);
01888 
01889     /* Find an editor to use */
01890     editorName = getenv("PSQL_EDITOR");
01891     if (!editorName)
01892         editorName = getenv("EDITOR");
01893     if (!editorName)
01894         editorName = getenv("VISUAL");
01895     if (!editorName)
01896         editorName = DEFAULT_EDITOR;
01897 
01898     /* Get line number argument, if we need it. */
01899     if (lineno > 0)
01900     {
01901         editor_lineno_arg = getenv("PSQL_EDITOR_LINENUMBER_ARG");
01902 #ifdef DEFAULT_EDITOR_LINENUMBER_ARG
01903         if (!editor_lineno_arg)
01904             editor_lineno_arg = DEFAULT_EDITOR_LINENUMBER_ARG;
01905 #endif
01906         if (!editor_lineno_arg)
01907         {
01908             psql_error("environment variable PSQL_EDITOR_LINENUMBER_ARG must be set to specify a line number\n");
01909             return false;
01910         }
01911     }
01912 
01913     /* Allocate sufficient memory for command line. */
01914     if (lineno > 0)
01915         sys = pg_malloc(strlen(editorName)
01916                         + strlen(editor_lineno_arg) + 10        /* for integer */
01917                         + 1 + strlen(fname) + 10 + 1);
01918     else
01919         sys = pg_malloc(strlen(editorName) + strlen(fname) + 10 + 1);
01920 
01921     /*
01922      * On Unix the EDITOR value should *not* be quoted, since it might include
01923      * switches, eg, EDITOR="pico -t"; it's up to the user to put quotes in it
01924      * if necessary.  But this policy is not very workable on Windows, due to
01925      * severe brain damage in their command shell plus the fact that standard
01926      * program paths include spaces.
01927      */
01928 #ifndef WIN32
01929     if (lineno > 0)
01930         sprintf(sys, "exec %s %s%d '%s'",
01931                 editorName, editor_lineno_arg, lineno, fname);
01932     else
01933         sprintf(sys, "exec %s '%s'",
01934                 editorName, fname);
01935 #else
01936     if (lineno > 0)
01937         sprintf(sys, SYSTEMQUOTE "\"%s\" %s%d \"%s\"" SYSTEMQUOTE,
01938                 editorName, editor_lineno_arg, lineno, fname);
01939     else
01940         sprintf(sys, SYSTEMQUOTE "\"%s\" \"%s\"" SYSTEMQUOTE,
01941                 editorName, fname);
01942 #endif
01943     result = system(sys);
01944     if (result == -1)
01945         psql_error("could not start editor \"%s\"\n", editorName);
01946     else if (result == 127)
01947         psql_error("could not start /bin/sh\n");
01948     free(sys);
01949 
01950     return result == 0;
01951 }
01952 
01953 
01954 /* call this one */
01955 static bool
01956 do_edit(const char *filename_arg, PQExpBuffer query_buf,
01957         int lineno, bool *edited)
01958 {
01959     char        fnametmp[MAXPGPATH];
01960     FILE       *stream = NULL;
01961     const char *fname;
01962     bool        error = false;
01963     int         fd;
01964 
01965     struct stat before,
01966                 after;
01967 
01968     if (filename_arg)
01969         fname = filename_arg;
01970     else
01971     {
01972         /* make a temp file to edit */
01973 #ifndef WIN32
01974         const char *tmpdir = getenv("TMPDIR");
01975 
01976         if (!tmpdir)
01977             tmpdir = "/tmp";
01978 #else
01979         char        tmpdir[MAXPGPATH];
01980         int         ret;
01981 
01982         ret = GetTempPath(MAXPGPATH, tmpdir);
01983         if (ret == 0 || ret > MAXPGPATH)
01984         {
01985             psql_error("could not locate temporary directory: %s\n",
01986                        !ret ? strerror(errno) : "");
01987             return false;
01988         }
01989 
01990         /*
01991          * No canonicalize_path() here. EDIT.EXE run from CMD.EXE prepends the
01992          * current directory to the supplied path unless we use only
01993          * backslashes, so we do that.
01994          */
01995 #endif
01996 #ifndef WIN32
01997         snprintf(fnametmp, sizeof(fnametmp), "%s%spsql.edit.%d.sql", tmpdir,
01998                  "/", (int) getpid());
01999 #else
02000         snprintf(fnametmp, sizeof(fnametmp), "%s%spsql.edit.%d.sql", tmpdir,
02001                "" /* trailing separator already present */ , (int) getpid());
02002 #endif
02003 
02004         fname = (const char *) fnametmp;
02005 
02006         fd = open(fname, O_WRONLY | O_CREAT | O_EXCL, 0600);
02007         if (fd != -1)
02008             stream = fdopen(fd, "w");
02009 
02010         if (fd == -1 || !stream)
02011         {
02012             psql_error("could not open temporary file \"%s\": %s\n", fname, strerror(errno));
02013             error = true;
02014         }
02015         else
02016         {
02017             unsigned int ql = query_buf->len;
02018 
02019             if (ql == 0 || query_buf->data[ql - 1] != '\n')
02020             {
02021                 appendPQExpBufferChar(query_buf, '\n');
02022                 ql++;
02023             }
02024 
02025             if (fwrite(query_buf->data, 1, ql, stream) != ql)
02026             {
02027                 psql_error("%s: %s\n", fname, strerror(errno));
02028                 fclose(stream);
02029                 remove(fname);
02030                 error = true;
02031             }
02032             else if (fclose(stream) != 0)
02033             {
02034                 psql_error("%s: %s\n", fname, strerror(errno));
02035                 remove(fname);
02036                 error = true;
02037             }
02038         }
02039     }
02040 
02041     if (!error && stat(fname, &before) != 0)
02042     {
02043         psql_error("%s: %s\n", fname, strerror(errno));
02044         error = true;
02045     }
02046 
02047     /* call editor */
02048     if (!error)
02049         error = !editFile(fname, lineno);
02050 
02051     if (!error && stat(fname, &after) != 0)
02052     {
02053         psql_error("%s: %s\n", fname, strerror(errno));
02054         error = true;
02055     }
02056 
02057     if (!error && before.st_mtime != after.st_mtime)
02058     {
02059         stream = fopen(fname, PG_BINARY_R);
02060         if (!stream)
02061         {
02062             psql_error("%s: %s\n", fname, strerror(errno));
02063             error = true;
02064         }
02065         else
02066         {
02067             /* read file back into query_buf */
02068             char        line[1024];
02069 
02070             resetPQExpBuffer(query_buf);
02071             while (fgets(line, sizeof(line), stream) != NULL)
02072                 appendPQExpBufferStr(query_buf, line);
02073 
02074             if (ferror(stream))
02075             {
02076                 psql_error("%s: %s\n", fname, strerror(errno));
02077                 error = true;
02078             }
02079             else if (edited)
02080             {
02081                 *edited = true;
02082             }
02083 
02084             fclose(stream);
02085         }
02086     }
02087 
02088     /* remove temp file */
02089     if (!filename_arg)
02090     {
02091         if (remove(fname) == -1)
02092         {
02093             psql_error("%s: %s\n", fname, strerror(errno));
02094             error = true;
02095         }
02096     }
02097 
02098     return !error;
02099 }
02100 
02101 
02102 
02103 /*
02104  * process_file
02105  *
02106  * Read commands from filename and then them to the main processing loop
02107  * Handler for \i and \ir, but can be used for other things as well.  Returns
02108  * MainLoop() error code.
02109  *
02110  * If use_relative_path is true and filename is not an absolute path, then open
02111  * the file from where the currently processed file (if any) is located.
02112  */
02113 int
02114 process_file(char *filename, bool single_txn, bool use_relative_path)
02115 {
02116     FILE       *fd;
02117     int         result;
02118     char       *oldfilename;
02119     char        relpath[MAXPGPATH];
02120     PGresult   *res;
02121 
02122     if (!filename)
02123     {
02124         fd = stdin;
02125         filename = NULL;
02126     }
02127     else if (strcmp(filename, "-") != 0)
02128     {
02129         canonicalize_path(filename);
02130 
02131         /*
02132          * If we were asked to resolve the pathname relative to the location
02133          * of the currently executing script, and there is one, and this is a
02134          * relative pathname, then prepend all but the last pathname component
02135          * of the current script to this pathname.
02136          */
02137         if (use_relative_path && pset.inputfile &&
02138             !is_absolute_path(filename) && !has_drive_prefix(filename))
02139         {
02140             strlcpy(relpath, pset.inputfile, sizeof(relpath));
02141             get_parent_directory(relpath);
02142             join_path_components(relpath, relpath, filename);
02143             canonicalize_path(relpath);
02144 
02145             filename = relpath;
02146         }
02147 
02148         fd = fopen(filename, PG_BINARY_R);
02149 
02150         if (!fd)
02151         {
02152             psql_error("%s: %s\n", filename, strerror(errno));
02153             return EXIT_FAILURE;
02154         }
02155     }
02156     else
02157     {
02158         fd = stdin;
02159         filename = "<stdin>";   /* for future error messages */
02160     }
02161 
02162     oldfilename = pset.inputfile;
02163     pset.inputfile = filename;
02164 
02165     if (single_txn)
02166     {
02167         if ((res = PSQLexec("BEGIN", false)) == NULL)
02168         {
02169             if (pset.on_error_stop)
02170             {
02171                 result = EXIT_USER;
02172                 goto error;
02173             }
02174         }
02175         else
02176             PQclear(res);
02177     }
02178 
02179     result = MainLoop(fd);
02180 
02181     if (single_txn)
02182     {
02183         if ((res = PSQLexec("COMMIT", false)) == NULL)
02184         {
02185             if (pset.on_error_stop)
02186             {
02187                 result = EXIT_USER;
02188                 goto error;
02189             }
02190         }
02191         else
02192             PQclear(res);
02193     }
02194 
02195 error:
02196     if (fd != stdin)
02197         fclose(fd);
02198 
02199     pset.inputfile = oldfilename;
02200     return result;
02201 }
02202 
02203 
02204 
02205 /*
02206  * do_pset
02207  *
02208  */
02209 static const char *
02210 _align2string(enum printFormat in)
02211 {
02212     switch (in)
02213     {
02214         case PRINT_NOTHING:
02215             return "nothing";
02216             break;
02217         case PRINT_UNALIGNED:
02218             return "unaligned";
02219             break;
02220         case PRINT_ALIGNED:
02221             return "aligned";
02222             break;
02223         case PRINT_WRAPPED:
02224             return "wrapped";
02225             break;
02226         case PRINT_HTML:
02227             return "html";
02228             break;
02229         case PRINT_LATEX:
02230             return "latex";
02231             break;
02232         case PRINT_LATEX_LONGTABLE:
02233             return "latex-longtable";
02234             break;
02235         case PRINT_TROFF_MS:
02236             return "troff-ms";
02237             break;
02238     }
02239     return "unknown";
02240 }
02241 
02242 
02243 bool
02244 do_pset(const char *param, const char *value, printQueryOpt *popt, bool quiet)
02245 {
02246     size_t      vallen = 0;
02247 
02248     Assert(param != NULL);
02249 
02250     if (value)
02251         vallen = strlen(value);
02252 
02253     /* set format */
02254     if (strcmp(param, "format") == 0)
02255     {
02256         if (!value)
02257             ;
02258         else if (pg_strncasecmp("unaligned", value, vallen) == 0)
02259             popt->topt.format = PRINT_UNALIGNED;
02260         else if (pg_strncasecmp("aligned", value, vallen) == 0)
02261             popt->topt.format = PRINT_ALIGNED;
02262         else if (pg_strncasecmp("wrapped", value, vallen) == 0)
02263             popt->topt.format = PRINT_WRAPPED;
02264         else if (pg_strncasecmp("html", value, vallen) == 0)
02265             popt->topt.format = PRINT_HTML;
02266         else if (pg_strncasecmp("latex", value, vallen) == 0)
02267             popt->topt.format = PRINT_LATEX;
02268         else if (pg_strncasecmp("latex-longtable", value, vallen) == 0)
02269             popt->topt.format = PRINT_LATEX_LONGTABLE;
02270         else if (pg_strncasecmp("troff-ms", value, vallen) == 0)
02271             popt->topt.format = PRINT_TROFF_MS;
02272         else
02273         {
02274             psql_error("\\pset: allowed formats are unaligned, aligned, wrapped, html, latex, troff-ms\n");
02275             return false;
02276         }
02277 
02278         if (!quiet)
02279             printf(_("Output format is %s.\n"), _align2string(popt->topt.format));
02280     }
02281 
02282     /* set table line style */
02283     else if (strcmp(param, "linestyle") == 0)
02284     {
02285         if (!value)
02286             ;
02287         else if (pg_strncasecmp("ascii", value, vallen) == 0)
02288             popt->topt.line_style = &pg_asciiformat;
02289         else if (pg_strncasecmp("old-ascii", value, vallen) == 0)
02290             popt->topt.line_style = &pg_asciiformat_old;
02291         else if (pg_strncasecmp("unicode", value, vallen) == 0)
02292             popt->topt.line_style = &pg_utf8format;
02293         else
02294         {
02295             psql_error("\\pset: allowed line styles are ascii, old-ascii, unicode\n");
02296             return false;
02297         }
02298 
02299         if (!quiet)
02300             printf(_("Line style is %s.\n"),
02301                    get_line_style(&popt->topt)->name);
02302     }
02303 
02304     /* set border style/width */
02305     else if (strcmp(param, "border") == 0)
02306     {
02307         if (value)
02308             popt->topt.border = atoi(value);
02309 
02310         if (!quiet)
02311             printf(_("Border style is %d.\n"), popt->topt.border);
02312     }
02313 
02314     /* set expanded/vertical mode */
02315     else if (strcmp(param, "x") == 0 || strcmp(param, "expanded") == 0 || strcmp(param, "vertical") == 0)
02316     {
02317         if (value && pg_strcasecmp(value, "auto") == 0)
02318             popt->topt.expanded = 2;
02319         else if (value)
02320             popt->topt.expanded = ParseVariableBool(value);
02321         else
02322             popt->topt.expanded = !popt->topt.expanded;
02323         if (!quiet)
02324         {
02325             if (popt->topt.expanded == 1)
02326                 printf(_("Expanded display is on.\n"));
02327             else if (popt->topt.expanded == 2)
02328                 printf(_("Expanded display is used automatically.\n"));
02329             else
02330                 printf(_("Expanded display is off.\n"));
02331         }
02332     }
02333 
02334     /* locale-aware numeric output */
02335     else if (strcmp(param, "numericlocale") == 0)
02336     {
02337         if (value)
02338             popt->topt.numericLocale = ParseVariableBool(value);
02339         else
02340             popt->topt.numericLocale = !popt->topt.numericLocale;
02341         if (!quiet)
02342         {
02343             if (popt->topt.numericLocale)
02344                 puts(_("Showing locale-adjusted numeric output."));
02345             else
02346                 puts(_("Locale-adjusted numeric output is off."));
02347         }
02348     }
02349 
02350     /* null display */
02351     else if (strcmp(param, "null") == 0)
02352     {
02353         if (value)
02354         {
02355             free(popt->nullPrint);
02356             popt->nullPrint = pg_strdup(value);
02357         }
02358         if (!quiet)
02359             printf(_("Null display is \"%s\".\n"), popt->nullPrint ? popt->nullPrint : "");
02360     }
02361 
02362     /* field separator for unaligned text */
02363     else if (strcmp(param, "fieldsep") == 0)
02364     {
02365         if (value)
02366         {
02367             free(popt->topt.fieldSep.separator);
02368             popt->topt.fieldSep.separator = pg_strdup(value);
02369             popt->topt.fieldSep.separator_zero = false;
02370         }
02371         if (!quiet)
02372         {
02373             if (popt->topt.fieldSep.separator_zero)
02374                 printf(_("Field separator is zero byte.\n"));
02375             else
02376                 printf(_("Field separator is \"%s\".\n"), popt->topt.fieldSep.separator);
02377         }
02378     }
02379 
02380     else if (strcmp(param, "fieldsep_zero") == 0)
02381     {
02382         free(popt->topt.fieldSep.separator);
02383         popt->topt.fieldSep.separator = NULL;
02384         popt->topt.fieldSep.separator_zero = true;
02385         if (!quiet)
02386             printf(_("Field separator is zero byte.\n"));
02387     }
02388 
02389     /* record separator for unaligned text */
02390     else if (strcmp(param, "recordsep") == 0)
02391     {
02392         if (value)
02393         {
02394             free(popt->topt.recordSep.separator);
02395             popt->topt.recordSep.separator = pg_strdup(value);
02396             popt->topt.recordSep.separator_zero = false;
02397         }
02398         if (!quiet)
02399         {
02400             if (popt->topt.recordSep.separator_zero)
02401                 printf(_("Record separator is zero byte.\n"));
02402             else if (strcmp(popt->topt.recordSep.separator, "\n") == 0)
02403                 printf(_("Record separator is <newline>."));
02404             else
02405                 printf(_("Record separator is \"%s\".\n"), popt->topt.recordSep.separator);
02406         }
02407     }
02408 
02409     else if (strcmp(param, "recordsep_zero") == 0)
02410     {
02411         free(popt->topt.recordSep.separator);
02412         popt->topt.recordSep.separator = NULL;
02413         popt->topt.recordSep.separator_zero = true;
02414         if (!quiet)
02415             printf(_("Record separator is zero byte.\n"));
02416     }
02417 
02418     /* toggle between full and tuples-only format */
02419     else if (strcmp(param, "t") == 0 || strcmp(param, "tuples_only") == 0)
02420     {
02421         if (value)
02422             popt->topt.tuples_only = ParseVariableBool(value);
02423         else
02424             popt->topt.tuples_only = !popt->topt.tuples_only;
02425         if (!quiet)
02426         {
02427             if (popt->topt.tuples_only)
02428                 puts(_("Showing only tuples."));
02429             else
02430                 puts(_("Tuples only is off."));
02431         }
02432     }
02433 
02434     /* set title override */
02435     else if (strcmp(param, "title") == 0)
02436     {
02437         free(popt->title);
02438         if (!value)
02439             popt->title = NULL;
02440         else
02441             popt->title = pg_strdup(value);
02442 
02443         if (!quiet)
02444         {
02445             if (popt->title)
02446                 printf(_("Title is \"%s\".\n"), popt->title);
02447             else
02448                 printf(_("Title is unset.\n"));
02449         }
02450     }
02451 
02452     /* set HTML table tag options */
02453     else if (strcmp(param, "T") == 0 || strcmp(param, "tableattr") == 0)
02454     {
02455         free(popt->topt.tableAttr);
02456         if (!value)
02457             popt->topt.tableAttr = NULL;
02458         else
02459             popt->topt.tableAttr = pg_strdup(value);
02460 
02461         if (!quiet)
02462         {
02463             if (popt->topt.tableAttr)
02464                 printf(_("Table attribute is \"%s\".\n"), popt->topt.tableAttr);
02465             else
02466                 printf(_("Table attributes unset.\n"));
02467         }
02468     }
02469 
02470     /* toggle use of pager */
02471     else if (strcmp(param, "pager") == 0)
02472     {
02473         if (value && pg_strcasecmp(value, "always") == 0)
02474             popt->topt.pager = 2;
02475         else if (value)
02476             if (ParseVariableBool(value))
02477                 popt->topt.pager = 1;
02478             else
02479                 popt->topt.pager = 0;
02480         else if (popt->topt.pager == 1)
02481             popt->topt.pager = 0;
02482         else
02483             popt->topt.pager = 1;
02484         if (!quiet)
02485         {
02486             if (popt->topt.pager == 1)
02487                 puts(_("Pager is used for long output."));
02488             else if (popt->topt.pager == 2)
02489                 puts(_("Pager is always used."));
02490             else
02491                 puts(_("Pager usage is off."));
02492         }
02493     }
02494 
02495     /* disable "(x rows)" footer */
02496     else if (strcmp(param, "footer") == 0)
02497     {
02498         if (value)
02499             popt->topt.default_footer = ParseVariableBool(value);
02500         else
02501             popt->topt.default_footer = !popt->topt.default_footer;
02502         if (!quiet)
02503         {
02504             if (popt->topt.default_footer)
02505                 puts(_("Default footer is on."));
02506             else
02507                 puts(_("Default footer is off."));
02508         }
02509     }
02510 
02511     /* set border style/width */
02512     else if (strcmp(param, "columns") == 0)
02513     {
02514         if (value)
02515             popt->topt.columns = atoi(value);
02516 
02517         if (!quiet)
02518             printf(_("Target width is %d.\n"), popt->topt.columns);
02519     }
02520 
02521     else
02522     {
02523         psql_error("\\pset: unknown option: %s\n", param);
02524         return false;
02525     }
02526 
02527     return true;
02528 }
02529 
02530 
02531 
02532 #ifndef WIN32
02533 #define DEFAULT_SHELL "/bin/sh"
02534 #else
02535 /*
02536  *  CMD.EXE is in different places in different Win32 releases so we
02537  *  have to rely on the path to find it.
02538  */
02539 #define DEFAULT_SHELL "cmd.exe"
02540 #endif
02541 
02542 static bool
02543 do_shell(const char *command)
02544 {
02545     int         result;
02546 
02547     if (!command)
02548     {
02549         char       *sys;
02550         const char *shellName;
02551 
02552         shellName = getenv("SHELL");
02553 #ifdef WIN32
02554         if (shellName == NULL)
02555             shellName = getenv("COMSPEC");
02556 #endif
02557         if (shellName == NULL)
02558             shellName = DEFAULT_SHELL;
02559 
02560         sys = pg_malloc(strlen(shellName) + 16);
02561 #ifndef WIN32
02562         sprintf(sys,
02563         /* See EDITOR handling comment for an explanation */
02564                 "exec %s", shellName);
02565 #else
02566         /* See EDITOR handling comment for an explanation */
02567         sprintf(sys, SYSTEMQUOTE "\"%s\"" SYSTEMQUOTE, shellName);
02568 #endif
02569         result = system(sys);
02570         free(sys);
02571     }
02572     else
02573         result = system(command);
02574 
02575     if (result == 127 || result == -1)
02576     {
02577         psql_error("\\!: failed\n");
02578         return false;
02579     }
02580     return true;
02581 }
02582 
02583 /*
02584  * do_watch -- handler for \watch
02585  *
02586  * We break this out of exec_command to avoid having to plaster "volatile"
02587  * onto a bunch of exec_command's variables to silence stupider compilers.
02588  */
02589 static bool
02590 do_watch(PQExpBuffer query_buf, long sleep)
02591 {
02592     printQueryOpt myopt = pset.popt;
02593     char        title[50];
02594 
02595     if (!query_buf || query_buf->len <= 0)
02596     {
02597         psql_error(_("\\watch cannot be used with an empty query\n"));
02598         return false;
02599     }
02600 
02601     /*
02602      * Set up rendering options, in particular, disable the pager, because
02603      * nobody wants to be prompted while watching the output of 'watch'.
02604      */
02605     myopt.nullPrint = NULL;
02606     myopt.topt.pager = 0;
02607 
02608     for (;;)
02609     {
02610         PGresult   *res;
02611         time_t      timer;
02612         long        i;
02613 
02614         /*
02615          * Prepare title for output.  XXX would it be better to use the time
02616          * of completion of the command?
02617          */
02618         timer = time(NULL);
02619         snprintf(title, sizeof(title), _("Watch every %lds\t%s"),
02620                  sleep, asctime(localtime(&timer)));
02621         myopt.title = title;
02622 
02623         /*
02624          * Run the query.  We use PSQLexec, which is kind of cheating, but
02625          * SendQuery doesn't let us suppress autocommit behavior.
02626          */
02627         res = PSQLexec(query_buf->data, false);
02628 
02629         /* PSQLexec handles failure results and returns NULL */
02630         if (res == NULL)
02631             break;
02632 
02633         /*
02634          * If SIGINT is sent while the query is processing, PSQLexec will
02635          * consume the interrupt.  The user's intention, though, is to cancel
02636          * the entire watch process, so detect a sent cancellation request and
02637          * exit in this case.
02638          */
02639         if (cancel_pressed)
02640         {
02641             PQclear(res);
02642             break;
02643         }
02644 
02645         switch (PQresultStatus(res))
02646         {
02647             case PGRES_TUPLES_OK:
02648                 printQuery(res, &myopt, pset.queryFout, pset.logfile);
02649                 break;
02650 
02651             case PGRES_EMPTY_QUERY:
02652                 psql_error(_("\\watch cannot be used with an empty query\n"));
02653                 PQclear(res);
02654                 return false;
02655 
02656             default:
02657                 /* should we fail for non-tuple-result commands? */
02658                 break;
02659         }
02660 
02661         PQclear(res);
02662 
02663         /*
02664          * Set up cancellation of 'watch' via SIGINT.  We redo this each time
02665          * through the loop since it's conceivable something inside PSQLexec
02666          * could change sigint_interrupt_jmp.
02667          */
02668         if (sigsetjmp(sigint_interrupt_jmp, 1) != 0)
02669             break;
02670 
02671         /*
02672          * Enable 'watch' cancellations and wait a while before running the
02673          * query again.  Break the sleep into short intervals since pg_usleep
02674          * isn't interruptible on some platforms.
02675          */
02676         sigint_interrupt_enabled = true;
02677         for (i = 0; i < sleep; i++)
02678         {
02679             pg_usleep(1000000L);
02680             if (cancel_pressed)
02681                 break;
02682         }
02683         sigint_interrupt_enabled = false;
02684     }
02685 
02686     return true;
02687 }
02688 
02689 /*
02690  * This function takes a function description, e.g. "x" or "x(int)", and
02691  * issues a query on the given connection to retrieve the function's OID
02692  * using a cast to regproc or regprocedure (as appropriate). The result,
02693  * if there is one, is returned at *foid.  Note that we'll fail if the
02694  * function doesn't exist OR if there are multiple matching candidates
02695  * OR if there's something syntactically wrong with the function description;
02696  * unfortunately it can be hard to tell the difference.
02697  */
02698 static bool
02699 lookup_function_oid(PGconn *conn, const char *desc, Oid *foid)
02700 {
02701     bool        result = true;
02702     PQExpBuffer query;
02703     PGresult   *res;
02704 
02705     query = createPQExpBuffer();
02706     printfPQExpBuffer(query, "SELECT ");
02707     appendStringLiteralConn(query, desc, conn);
02708     appendPQExpBuffer(query, "::pg_catalog.%s::pg_catalog.oid",
02709                       strchr(desc, '(') ? "regprocedure" : "regproc");
02710 
02711     res = PQexec(conn, query->data);
02712     if (PQresultStatus(res) == PGRES_TUPLES_OK && PQntuples(res) == 1)
02713         *foid = atooid(PQgetvalue(res, 0, 0));
02714     else
02715     {
02716         minimal_error_message(res);
02717         result = false;
02718     }
02719 
02720     PQclear(res);
02721     destroyPQExpBuffer(query);
02722 
02723     return result;
02724 }
02725 
02726 /*
02727  * Fetches the "CREATE OR REPLACE FUNCTION ..." command that describes the
02728  * function with the given OID.  If successful, the result is stored in buf.
02729  */
02730 static bool
02731 get_create_function_cmd(PGconn *conn, Oid oid, PQExpBuffer buf)
02732 {
02733     bool        result = true;
02734     PQExpBuffer query;
02735     PGresult   *res;
02736 
02737     query = createPQExpBuffer();
02738     printfPQExpBuffer(query, "SELECT pg_catalog.pg_get_functiondef(%u)", oid);
02739 
02740     res = PQexec(conn, query->data);
02741     if (PQresultStatus(res) == PGRES_TUPLES_OK && PQntuples(res) == 1)
02742     {
02743         resetPQExpBuffer(buf);
02744         appendPQExpBufferStr(buf, PQgetvalue(res, 0, 0));
02745     }
02746     else
02747     {
02748         minimal_error_message(res);
02749         result = false;
02750     }
02751 
02752     PQclear(res);
02753     destroyPQExpBuffer(query);
02754 
02755     return result;
02756 }
02757 
02758 /*
02759  * If the given argument of \ef ends with a line number, delete the line
02760  * number from the argument string and return it as an integer.  (We need
02761  * this kluge because we're too lazy to parse \ef's function name argument
02762  * carefully --- we just slop it up in OT_WHOLE_LINE mode.)
02763  *
02764  * Returns -1 if no line number is present, 0 on error, or a positive value
02765  * on success.
02766  */
02767 static int
02768 strip_lineno_from_funcdesc(char *func)
02769 {
02770     char       *c;
02771     int         lineno;
02772 
02773     if (!func || func[0] == '\0')
02774         return -1;
02775 
02776     c = func + strlen(func) - 1;
02777 
02778     /*
02779      * This business of parsing backwards is dangerous as can be in a
02780      * multibyte environment: there is no reason to believe that we are
02781      * looking at the first byte of a character, nor are we necessarily
02782      * working in a "safe" encoding.  Fortunately the bitpatterns we are
02783      * looking for are unlikely to occur as non-first bytes, but beware of
02784      * trying to expand the set of cases that can be recognized.  We must
02785      * guard the <ctype.h> macros by using isascii() first, too.
02786      */
02787 
02788     /* skip trailing whitespace */
02789     while (c > func && isascii((unsigned char) *c) && isspace((unsigned char) *c))
02790         c--;
02791 
02792     /* must have a digit as last non-space char */
02793     if (c == func || !isascii((unsigned char) *c) || !isdigit((unsigned char) *c))
02794         return -1;
02795 
02796     /* find start of digit string */
02797     while (c > func && isascii((unsigned char) *c) && isdigit((unsigned char) *c))
02798         c--;
02799 
02800     /* digits must be separated from func name by space or closing paren */
02801     /* notice also that we are not allowing an empty func name ... */
02802     if (c == func || !isascii((unsigned char) *c) ||
02803         !(isspace((unsigned char) *c) || *c == ')'))
02804         return -1;
02805 
02806     /* parse digit string */
02807     c++;
02808     lineno = atoi(c);
02809     if (lineno < 1)
02810     {
02811         psql_error("invalid line number: %s\n", c);
02812         return 0;
02813     }
02814 
02815     /* strip digit string from func */
02816     *c = '\0';
02817 
02818     return lineno;
02819 }
02820 
02821 /*
02822  * Report just the primary error; this is to avoid cluttering the output
02823  * with, for instance, a redisplay of the internally generated query
02824  */
02825 static void
02826 minimal_error_message(PGresult *res)
02827 {
02828     PQExpBuffer msg;
02829     const char *fld;
02830 
02831     msg = createPQExpBuffer();
02832 
02833     fld = PQresultErrorField(res, PG_DIAG_SEVERITY);
02834     if (fld)
02835         printfPQExpBuffer(msg, "%s:  ", fld);
02836     else
02837         printfPQExpBuffer(msg, "ERROR:  ");
02838     fld = PQresultErrorField(res, PG_DIAG_MESSAGE_PRIMARY);
02839     if (fld)
02840         appendPQExpBufferStr(msg, fld);
02841     else
02842         appendPQExpBufferStr(msg, "(not available)");
02843     appendPQExpBufferStr(msg, "\n");
02844 
02845     psql_error("%s", msg->data);
02846 
02847     destroyPQExpBuffer(msg);
02848 }