]> granicus.if.org Git - postgresql/blobdiff - src/bin/psql/startup.c
Append major version number and for libraries soname major version number
[postgresql] / src / bin / psql / startup.c
index e19db7a7ae3cd7488c45882356d0e5fac80a013e..c8602161c073ce1972339d762d98b64ea0cbaeb9 100644 (file)
@@ -1,9 +1,9 @@
 /*
  * psql - the PostgreSQL interactive terminal
  *
- * Copyright 2000 by PostgreSQL Global Development Group
+ * Copyright (c) 2000-2008, PostgreSQL Global Development Group
  *
- * $Header: /cvsroot/pgsql/src/bin/psql/startup.c,v 1.60 2002/06/20 20:29:42 momjian Exp $
+ * $PostgreSQL: pgsql/src/bin/psql/startup.c,v 1.152 2008/12/11 07:34:08 petere Exp $
  */
 #include "postgres_fe.h"
 
 #include <unistd.h>
 #else                                                  /* WIN32 */
 #include <io.h>
-#include <windows.h>
 #include <win32.h>
 #endif   /* WIN32 */
 
-#ifdef HAVE_GETOPT_H
-#include <getopt.h>
+#include "getopt_long.h"
+
+#ifndef HAVE_INT_OPTRESET
+int                    optreset;
 #endif
 
-#ifdef ENABLE_NLS
 #include <locale.h>
-#endif
 
-#include "libpq-fe.h"
 
 #include "command.h"
 #include "common.h"
 #include "help.h"
 #include "input.h"
 #include "mainloop.h"
-#include "print.h"
 #include "settings.h"
-#include "variables.h"
 
-#ifdef MULTIBYTE
-#include "mb/pg_wchar.h"
-#else
-/* XXX Grand unified hard-coded badness; this should go into libpq */
-#define pg_encoding_to_char(x) "SQL_ASCII"
-#endif
+
 
 /*
  * Global psql options
  */
 PsqlSettings pset;
 
+#ifndef WIN32
+#define SYSPSQLRC      "psqlrc"
+#define PSQLRC         ".psqlrc"
+#else
+#define SYSPSQLRC      "psqlrc"
+#define PSQLRC         "psqlrc.conf"
+#endif
 
 /*
  * Structures to pass information between the option parsing routine
@@ -69,26 +67,20 @@ struct adhoc_opts
        char       *host;
        char       *port;
        char       *username;
+       char       *logfilename;
        enum _actions action;
        char       *action_string;
        bool            no_readline;
        bool            no_psqlrc;
+       bool            single_txn;
 };
 
-static void
-                       parse_psql_options(int argc, char *argv[], struct adhoc_opts * options);
-
-static void
-                       process_psqlrc(void);
-
-static void
-                       showVersion(void);
-
-#ifdef USE_SSL
-static void
-                       printSSLInfo(void);
-#endif
-
+static void parse_psql_options(int argc, char *argv[],
+                                  struct adhoc_opts * options);
+static void process_psqlrc(char *argv0);
+static void process_psqlrc_file(char *filename);
+static void showVersion(void);
+static void EstablishVariableSpace(void);
 
 /*
  *
@@ -100,21 +92,11 @@ main(int argc, char *argv[])
 {
        struct adhoc_opts options;
        int                     successResult;
-
-       char       *username = NULL;
        char       *password = NULL;
-       bool            need_pass;
+       char       *password_prompt = NULL;
+       bool            new_pass;
 
-#ifdef ENABLE_NLS
-       setlocale(LC_ALL, "");
-       bindtextdomain("psql", LOCALEDIR);
-       textdomain("psql");
-#endif
-
-       if (!strrchr(argv[0], '/'))
-               pset.progname = argv[0];
-       else
-               pset.progname = strrchr(argv[0], '/') + 1;
+       set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("psql"));
 
        if (argc > 1)
        {
@@ -130,23 +112,31 @@ main(int argc, char *argv[])
                }
        }
 
+#ifdef WIN32
+       setvbuf(stderr, NULL, _IONBF, 0);
+#endif
+
+       setup_cancel_handler();
+
+       pset.progname = get_progname(argv[0]);
+
+       pset.db = NULL;
+       setDecimalLocale();
+       pset.encoding = PQenv2encoding();
+       pset.queryFout = stdout;
+       pset.queryFoutPipe = false;
        pset.cur_cmd_source = stdin;
        pset.cur_cmd_interactive = false;
-       pset.encoding = PQenv2encoding();
 
-       pset.vars = CreateVariableSpace();
-       if (!pset.vars)
-       {
-               fprintf(stderr, gettext("%s: out of memory\n"), pset.progname);
-               exit(EXIT_FAILURE);
-       }
+       /* We rely on unmentioned fields of pset.popt to start out 0/false/NULL */
        pset.popt.topt.format = PRINT_ALIGNED;
-       pset.queryFout = stdout;
        pset.popt.topt.border = 1;
-       pset.popt.topt.pager = true;
+       pset.popt.topt.pager = 1;
+       pset.popt.topt.start_table = true;
+       pset.popt.topt.stop_table = true;
        pset.popt.default_footer = true;
-
-       SetVariable(pset.vars, "VERSION", PG_VERSION_STR);
+       /* We must get COLUMNS here before readline() sets it */
+       pset.popt.topt.env_columns = getenv("COLUMNS") ? atoi(getenv("COLUMNS")) : 0;
 
        pset.notty = (!isatty(fileno(stdin)) || !isatty(fileno(stdout)));
 
@@ -157,51 +147,59 @@ main(int argc, char *argv[])
        pset.getPassword = false;
 #endif
 
+       EstablishVariableSpace();
+
+       SetVariable(pset.vars, "VERSION", PG_VERSION_STR);
+
+       /* Default values for variables */
+       SetVariableBool(pset.vars, "AUTOCOMMIT");
+       SetVariable(pset.vars, "VERBOSITY", "default");
+       SetVariable(pset.vars, "PROMPT1", DEFAULT_PROMPT1);
+       SetVariable(pset.vars, "PROMPT2", DEFAULT_PROMPT2);
+       SetVariable(pset.vars, "PROMPT3", DEFAULT_PROMPT3);
+
        parse_psql_options(argc, argv, &options);
 
        if (!pset.popt.topt.fieldSep)
-               pset.popt.topt.fieldSep = xstrdup(DEFAULT_FIELD_SEP);
+               pset.popt.topt.fieldSep = pg_strdup(DEFAULT_FIELD_SEP);
        if (!pset.popt.topt.recordSep)
-               pset.popt.topt.recordSep = xstrdup(DEFAULT_RECORD_SEP);
+               pset.popt.topt.recordSep = pg_strdup(DEFAULT_RECORD_SEP);
 
-       if (options.username)
+       if (options.username == NULL)
+               password_prompt = pg_strdup(_("Password: "));
+       else
        {
-               /*
-                * The \001 is a hack to support the deprecated -u option which
-                * issues a username prompt. The recommended option is -U followed
-                * by the name on the command line.
-                */
-               if (strcmp(options.username, "\001") == 0)
-                       username = simple_prompt("User name: ", 100, true);
-               else
-                       username = strdup(options.username);
+               password_prompt = malloc(strlen(_("Password for user %s: ")) - 2 +
+                                                                strlen(options.username) + 1);
+               sprintf(password_prompt, _("Password for user %s: "),
+                               options.username);
        }
 
        if (pset.getPassword)
-               password = simple_prompt("Password: ", 100, false);
+               password = simple_prompt(password_prompt, 100, false);
 
        /* loop until we have a password if requested by backend */
        do
        {
-               need_pass = false;
+               new_pass = false;
                pset.db = PQsetdbLogin(options.host, options.port, NULL, NULL,
-                       options.action == ACT_LIST_DB ? "template1" : options.dbname,
-                                                          username, password);
+                                       options.action == ACT_LIST_DB && options.dbname == NULL ?
+                                                          "postgres" : options.dbname,
+                                                          options.username, password);
 
                if (PQstatus(pset.db) == CONNECTION_BAD &&
-                       strcmp(PQerrorMessage(pset.db), "fe_sendauth: no password supplied\n") == 0 &&
+                       PQconnectionNeedsPassword(pset.db) &&
+                       password == NULL &&
                        !feof(stdin))
                {
                        PQfinish(pset.db);
-                       need_pass = true;
-                       free(password);
-                       password = NULL;
-                       password = simple_prompt("Password: ", 100, false);
+                       password = simple_prompt(password_prompt, 100, false);
+                       new_pass = true;
                }
-       } while (need_pass);
+       } while (new_pass);
 
-       free(username);
        free(password);
+       free(password_prompt);
 
        if (PQstatus(pset.db) == CONNECTION_BAD)
        {
@@ -212,11 +210,7 @@ main(int argc, char *argv[])
 
        PQsetNoticeProcessor(pset.db, NoticeProcessor, NULL);
 
-       /*
-        * We need to save the encoding because we want to have it available
-        * even if the database connection goes bad.
-        */
-       pset.encoding = PQclientEncoding(pset.db);
+       SyncVariables();
 
        if (options.action == ACT_LIST_DB)
        {
@@ -226,11 +220,13 @@ main(int argc, char *argv[])
                exit(success ? EXIT_SUCCESS : EXIT_FAILURE);
        }
 
-       SetVariable(pset.vars, "DBNAME", PQdb(pset.db));
-       SetVariable(pset.vars, "USER", PQuser(pset.db));
-       SetVariable(pset.vars, "HOST", PQhost(pset.db));
-       SetVariable(pset.vars, "PORT", PQport(pset.db));
-       SetVariable(pset.vars, "ENCODING", pg_encoding_to_char(pset.encoding));
+       if (options.logfilename)
+       {
+               pset.logfile = fopen(options.logfilename, "a");
+               if (!pset.logfile)
+                       fprintf(stderr, _("%s: could not open log file \"%s\": %s\n"),
+                                       pset.progname, options.logfilename, strerror(errno));
+       }
 
        /*
         * Now find something to do
@@ -242,9 +238,9 @@ main(int argc, char *argv[])
        if (options.action == ACT_FILE && strcmp(options.action_string, "-") != 0)
        {
                if (!options.no_psqlrc)
-                       process_psqlrc();
+                       process_psqlrc(argv[0]);
 
-               successResult = process_file(options.action_string);
+               successResult = process_file(options.action_string, options.single_txn);
        }
 
        /*
@@ -252,12 +248,20 @@ main(int argc, char *argv[])
         */
        else if (options.action == ACT_SINGLE_SLASH)
        {
-               const char *value;
+               PsqlScanState scan_state;
 
-               if ((value = GetVariable(pset.vars, "ECHO")) && strcmp(value, "all") == 0)
+               if (pset.echo == PSQL_ECHO_ALL)
                        puts(options.action_string);
-               successResult = HandleSlashCmds(options.action_string, NULL, NULL, NULL) != CMD_ERROR
+
+               scan_state = psql_scan_create();
+               psql_scan_setup(scan_state,
+                                               options.action_string,
+                                               strlen(options.action_string));
+
+               successResult = HandleSlashCmds(scan_state, NULL) != PSQL_CMD_ERROR
                        ? EXIT_SUCCESS : EXIT_FAILURE;
+
+               psql_scan_destroy(scan_state);
        }
 
        /*
@@ -265,10 +269,9 @@ main(int argc, char *argv[])
         */
        else if (options.action == ACT_SINGLE_QUERY)
        {
-               const char *value;
-
-               if ((value = GetVariable(pset.vars, "ECHO")) && strcmp(value, "all") == 0)
+               if (pset.echo == PSQL_ECHO_ALL)
                        puts(options.action_string);
+
                successResult = SendQuery(options.action_string)
                        ? EXIT_SUCCESS : EXIT_FAILURE;
        }
@@ -278,34 +281,23 @@ main(int argc, char *argv[])
         */
        else
        {
-               pset.issuper = test_superuser(PQuser(pset.db));
-               if (!QUIET() && !pset.notty)
-               {
-                       printf(gettext("Welcome to %s, the PostgreSQL interactive terminal.\n\n"
-                                                  "Type:  \\copyright for distribution terms\n"
-                                                  "       \\h for help with SQL commands\n"
-                                          "       \\? for help on internal slash commands\n"
-                         "       \\g or terminate with semicolon to execute query\n"
-                                                  "       \\q to quit\n\n"),
-                                  pset.progname);
-#ifdef USE_SSL
-                       printSSLInfo();
-#endif
-               }
-
-               SetVariable(pset.vars, "PROMPT1", DEFAULT_PROMPT1);
-               SetVariable(pset.vars, "PROMPT2", DEFAULT_PROMPT2);
-               SetVariable(pset.vars, "PROMPT3", DEFAULT_PROMPT3);
                if (!options.no_psqlrc)
-                       process_psqlrc();
+                       process_psqlrc(argv[0]);
+
+               connection_warnings();
+               if (!pset.quiet && !pset.notty)
+                       printf(_("Type \"help\" for help.\n\n"));
                if (!pset.notty)
                        initializeInput(options.no_readline ? 0 : 1);
                if (options.action_string)              /* -f - was used */
                        pset.inputfile = "<stdin>";
+
                successResult = MainLoop(stdin);
        }
 
        /* clean up */
+       if (pset.logfile)
+               fclose(pset.logfile);
        PQfinish(pset.db);
        setQFout(NULL);
 
@@ -313,23 +305,13 @@ main(int argc, char *argv[])
 }
 
 
-
 /*
  * Parse command line options
  */
 
-#ifdef WIN32
-/* getopt is not in the standard includes on Win32 */
-int                    getopt(int, char *const[], const char *);
-
-/* And it requires progname to be set */
-char      *__progname = "psql";
-#endif
-
 static void
 parse_psql_options(int argc, char *argv[], struct adhoc_opts * options)
 {
-#ifdef HAVE_GETOPT_LONG
        static struct option long_options[] =
        {
                {"echo-all", no_argument, NULL, 'a'},
@@ -343,7 +325,9 @@ parse_psql_options(int argc, char *argv[], struct adhoc_opts * options)
                {"host", required_argument, NULL, 'h'},
                {"html", no_argument, NULL, 'H'},
                {"list", no_argument, NULL, 'l'},
+               {"log-file", required_argument, NULL, 'L'},
                {"no-readline", no_argument, NULL, 'n'},
+               {"single-transaction", no_argument, NULL, '1'},
                {"output", required_argument, NULL, 'o'},
                {"port", required_argument, NULL, 'p'},
                {"pset", required_argument, NULL, 'P'},
@@ -365,25 +349,14 @@ parse_psql_options(int argc, char *argv[], struct adhoc_opts * options)
        };
 
        int                     optindex;
-#endif   /* HAVE_GETOPT_LONG */
-
        extern char *optarg;
        extern int      optind;
        int                     c;
-       bool            used_old_u_option = false;
 
        memset(options, 0, sizeof *options);
 
-#ifdef HAVE_GETOPT_LONG
-       while ((c = getopt_long(argc, argv, "aAc:d:eEf:F:h:Hlno:p:P:qR:sStT:uU:v:VWxX?", long_options, &optindex)) != -1)
-#else                                                  /* not HAVE_GETOPT_LONG */
-
-       /*
-        * Be sure to leave the '-' in here, so we can catch accidental long
-        * options.
-        */
-       while ((c = getopt(argc, argv, "aAc:d:eEf:F:h:Hlno:p:P:qR:sStT:uU:v:VWxX?-")) != -1)
-#endif   /* not HAVE_GETOPT_LONG */
+       while ((c = getopt_long(argc, argv, "aAc:d:eEf:F:h:HlL:no:p:P:qR:sStT:U:v:VWxX?1",
+                                                       long_options, &optindex)) != -1)
        {
                switch (c)
                {
@@ -417,7 +390,7 @@ parse_psql_options(int argc, char *argv[], struct adhoc_opts * options)
                                options->action_string = optarg;
                                break;
                        case 'F':
-                               pset.popt.topt.fieldSep = xstrdup(optarg);
+                               pset.popt.topt.fieldSep = pg_strdup(optarg);
                                break;
                        case 'h':
                                options->host = optarg;
@@ -428,6 +401,9 @@ parse_psql_options(int argc, char *argv[], struct adhoc_opts * options)
                        case 'l':
                                options->action = ACT_LIST_DB;
                                break;
+                       case 'L':
+                               options->logfilename = optarg;
+                               break;
                        case 'n':
                                options->no_readline = true;
                                break;
@@ -443,7 +419,7 @@ parse_psql_options(int argc, char *argv[], struct adhoc_opts * options)
                                        char       *equal_loc;
                                        bool            result;
 
-                                       value = xstrdup(optarg);
+                                       value = pg_strdup(optarg);
                                        equal_loc = strchr(value, '=');
                                        if (!equal_loc)
                                                result = do_pset(value, NULL, &pset.popt, true);
@@ -455,7 +431,7 @@ parse_psql_options(int argc, char *argv[], struct adhoc_opts * options)
 
                                        if (!result)
                                        {
-                                               fprintf(stderr, gettext("%s: couldn't set printing parameter %s\n"), pset.progname, value);
+                                               fprintf(stderr, _("%s: could not set printing parameter \"%s\"\n"), pset.progname, value);
                                                exit(EXIT_FAILURE);
                                        }
 
@@ -466,7 +442,7 @@ parse_psql_options(int argc, char *argv[], struct adhoc_opts * options)
                                SetVariableBool(pset.vars, "QUIET");
                                break;
                        case 'R':
-                               pset.popt.topt.recordSep = xstrdup(optarg);
+                               pset.popt.topt.recordSep = pg_strdup(optarg);
                                break;
                        case 's':
                                SetVariableBool(pset.vars, "SINGLESTEP");
@@ -478,14 +454,7 @@ parse_psql_options(int argc, char *argv[], struct adhoc_opts * options)
                                pset.popt.topt.tuples_only = true;
                                break;
                        case 'T':
-                               pset.popt.topt.tableAttr = xstrdup(optarg);
-                               break;
-                       case 'u':
-                               pset.getPassword = true;
-                               options->username = "\001";             /* hopefully nobody has
-                                                                                                * that username */
-                               /* this option is out */
-                               used_old_u_option = true;
+                               pset.popt.topt.tableAttr = pg_strdup(optarg);
                                break;
                        case 'U':
                                options->username = optarg;
@@ -495,13 +464,13 @@ parse_psql_options(int argc, char *argv[], struct adhoc_opts * options)
                                        char       *value;
                                        char       *equal_loc;
 
-                                       value = xstrdup(optarg);
+                                       value = pg_strdup(optarg);
                                        equal_loc = strchr(value, '=');
                                        if (!equal_loc)
                                        {
                                                if (!DeleteVariable(pset.vars, value))
                                                {
-                                                       fprintf(stderr, gettext("%s: could not delete variable %s\n"),
+                                                       fprintf(stderr, _("%s: could not delete variable \"%s\"\n"),
                                                                        pset.progname, value);
                                                        exit(EXIT_FAILURE);
                                                }
@@ -511,7 +480,7 @@ parse_psql_options(int argc, char *argv[], struct adhoc_opts * options)
                                                *equal_loc = '\0';
                                                if (!SetVariable(pset.vars, value, equal_loc + 1))
                                                {
-                                                       fprintf(stderr, gettext("%s: could not set variable %s\n"),
+                                                       fprintf(stderr, _("%s: could not set variable \"%s\"\n"),
                                                                        pset.progname, value);
                                                        exit(EXIT_FAILURE);
                                                }
@@ -532,6 +501,9 @@ parse_psql_options(int argc, char *argv[], struct adhoc_opts * options)
                        case 'X':
                                options->no_psqlrc = true;
                                break;
+                       case '1':
+                               options->single_txn = true;
+                               break;
                        case '?':
                                /* Actual help option given */
                                if (strcmp(argv[optind - 1], "-?") == 0 || strcmp(argv[optind - 1], "--help") == 0)
@@ -542,22 +514,13 @@ parse_psql_options(int argc, char *argv[], struct adhoc_opts * options)
                                /* unknown option reported by getopt */
                                else
                                {
-                                       fprintf(stderr, gettext("Try '%s --help' for more information.\n"),
+                                       fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
                                                        pset.progname);
                                        exit(EXIT_FAILURE);
                                }
                                break;
-#ifndef HAVE_GETOPT_LONG
-                       case '-':
-                               fprintf(stderr,
-                                               gettext("%s was compiled without support for long options.\n"
-                                                "Use --help for help on invocation options.\n"),
-                                               pset.progname);
-                               exit(EXIT_FAILURE);
-                               break;
-#endif
                        default:
-                               fprintf(stderr, gettext("Try '%s --help' for more information.\n"),
+                               fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
                                                pset.progname);
                                exit(EXIT_FAILURE);
                                break;
@@ -565,8 +528,7 @@ parse_psql_options(int argc, char *argv[], struct adhoc_opts * options)
        }
 
        /*
-        * if we still have arguments, use it as the database name and
-        * username
+        * if we still have arguments, use it as the database name and username
         */
        while (argc - optind >= 1)
        {
@@ -574,60 +536,62 @@ parse_psql_options(int argc, char *argv[], struct adhoc_opts * options)
                        options->dbname = argv[optind];
                else if (!options->username)
                        options->username = argv[optind];
-               else if (!QUIET())
-                       fprintf(stderr, gettext("%s: warning: extra option %s ignored\n"),
+               else if (!pset.quiet)
+                       fprintf(stderr, _("%s: warning: extra command-line argument \"%s\" ignored\n"),
                                        pset.progname, argv[optind]);
 
                optind++;
        }
-
-       if (used_old_u_option && !QUIET())
-               fprintf(stderr, gettext("%s: Warning: The -u option is deprecated. Use -U.\n"), pset.progname);
-
 }
 
 
-
 /*
  * Load .psqlrc file, if found.
  */
 static void
-process_psqlrc(void)
+process_psqlrc(char *argv0)
 {
-       char       *psqlrc;
-       char       *home;
+       char            home[MAXPGPATH];
+       char            rc_file[MAXPGPATH];
+       char            my_exec_path[MAXPGPATH];
+       char            etc_path[MAXPGPATH];
 
-#ifdef WIN32
-#define R_OK 0
-#endif
+       find_my_exec(argv0, my_exec_path);
+       get_etc_path(my_exec_path, etc_path);
 
-       /* Look for one in the home dir */
-       home = getenv("HOME");
+       snprintf(rc_file, MAXPGPATH, "%s/%s", etc_path, SYSPSQLRC);
+       process_psqlrc_file(rc_file);
 
-       if (home)
+       if (get_home_path(home))
        {
-               psqlrc = malloc(strlen(home) + 20);
-               if (!psqlrc)
-               {
-                       fprintf(stderr, gettext("%s: out of memory\n"), pset.progname);
-                       exit(EXIT_FAILURE);
-               }
-
-               sprintf(psqlrc, "%s/.psqlrc-" PG_VERSION, home);
-               if (access(psqlrc, R_OK) == 0)
-                       process_file(psqlrc);
-               else
-               {
-                       sprintf(psqlrc, "%s/.psqlrc", home);
-                       if (access(psqlrc, R_OK) == 0)
-                               process_file(psqlrc);
-               }
-               free(psqlrc);
+               snprintf(rc_file, MAXPGPATH, "%s/%s", home, PSQLRC);
+               process_psqlrc_file(rc_file);
        }
 }
 
 
 
+static void
+process_psqlrc_file(char *filename)
+{
+       char       *psqlrc;
+
+#if defined(WIN32) && (!defined(__MINGW32__))
+#define R_OK 4
+#endif
+
+       psqlrc = pg_malloc(strlen(filename) + 1 + strlen(PG_VERSION) + 1);
+       sprintf(psqlrc, "%s-%s", filename, PG_VERSION);
+
+       if (access(psqlrc, R_OK) == 0)
+               (void) process_file(psqlrc, false);
+       else if (access(filename, R_OK) == 0)
+               (void) process_file(filename, false);
+       free(psqlrc);
+}
+
+
+
 /* showVersion
  *
  * This output format is intended to match GNU standards.
@@ -637,55 +601,163 @@ showVersion(void)
 {
        puts("psql (PostgreSQL) " PG_VERSION);
 
-#if defined(USE_READLINE) || defined(MULTIBYTE)
-       fputs(gettext("contains support for: "), stdout);
-
-#ifdef USE_READLINE
-       fputs(gettext("readline"), stdout);
-#define _Feature
+#if defined(USE_READLINE)
+       puts(_("contains support for command-line editing"));
 #endif
+}
 
-#ifdef MULTIBYTE
-#ifdef _Feature
-       fputs(", ", stdout);
-#else
-#define _Feature
-#endif
-       fputs(gettext("multibyte"), stdout);
-#endif
 
-#undef _Feature
 
-       puts("");
-#endif
+/*
+ * Assign hooks for psql variables.
+ *
+ * This isn't an amazingly good place for them, but neither is anywhere else.
+ */
 
-       puts(gettext("Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group\n"
-                                "Portions Copyright (c) 1996, Regents of the University of California\n"
-       "Read the file COPYRIGHT or use the command \\copyright to see the\n"
-                                "usage and distribution terms."));
+static void
+autocommit_hook(const char *newval)
+{
+       pset.autocommit = ParseVariableBool(newval);
 }
 
+static void
+on_error_stop_hook(const char *newval)
+{
+       pset.on_error_stop = ParseVariableBool(newval);
+}
 
+static void
+quiet_hook(const char *newval)
+{
+       pset.quiet = ParseVariableBool(newval);
+}
 
-/*
- * printSSLInfo
- *
- * Prints information about the current SSL connection, if SSL is in use
- */
-#ifdef USE_SSL
 static void
-printSSLInfo(void)
+singleline_hook(const char *newval)
 {
-       int                     sslbits = -1;
-       SSL                *ssl;
+       pset.singleline = ParseVariableBool(newval);
+}
 
-       ssl = PQgetssl(pset.db);
-       if (!ssl)
-               return;                                 /* no SSL */
+static void
+singlestep_hook(const char *newval)
+{
+       pset.singlestep = ParseVariableBool(newval);
+}
 
-       SSL_get_cipher_bits(ssl, &sslbits);
-       printf(gettext("SSL connection (cipher: %s, bits: %i)\n\n"),
-                  SSL_get_cipher(ssl), sslbits);
+static void
+fetch_count_hook(const char *newval)
+{
+       pset.fetch_count = ParseVariableNum(newval, -1, -1, false);
 }
 
-#endif
+static void
+echo_hook(const char *newval)
+{
+       if (newval == NULL)
+               pset.echo = PSQL_ECHO_NONE;
+       else if (strcmp(newval, "queries") == 0)
+               pset.echo = PSQL_ECHO_QUERIES;
+       else if (strcmp(newval, "all") == 0)
+               pset.echo = PSQL_ECHO_ALL;
+       else
+               pset.echo = PSQL_ECHO_NONE;
+}
+
+static void
+echo_hidden_hook(const char *newval)
+{
+       if (newval == NULL)
+               pset.echo_hidden = PSQL_ECHO_HIDDEN_OFF;
+       else if (strcmp(newval, "noexec") == 0)
+               pset.echo_hidden = PSQL_ECHO_HIDDEN_NOEXEC;
+       else if (pg_strcasecmp(newval, "off") == 0)
+               pset.echo_hidden = PSQL_ECHO_HIDDEN_OFF;
+       else
+               pset.echo_hidden = PSQL_ECHO_HIDDEN_ON;
+}
+
+static void
+on_error_rollback_hook(const char *newval)
+{
+       if (newval == NULL)
+               pset.on_error_rollback = PSQL_ERROR_ROLLBACK_OFF;
+       else if (pg_strcasecmp(newval, "interactive") == 0)
+               pset.on_error_rollback = PSQL_ERROR_ROLLBACK_INTERACTIVE;
+       else if (pg_strcasecmp(newval, "off") == 0)
+               pset.on_error_rollback = PSQL_ERROR_ROLLBACK_OFF;
+       else
+               pset.on_error_rollback = PSQL_ERROR_ROLLBACK_ON;
+}
+
+static void
+histcontrol_hook(const char *newval)
+{
+       if (newval == NULL)
+               pset.histcontrol = hctl_none;
+       else if (strcmp(newval, "ignorespace") == 0)
+               pset.histcontrol = hctl_ignorespace;
+       else if (strcmp(newval, "ignoredups") == 0)
+               pset.histcontrol = hctl_ignoredups;
+       else if (strcmp(newval, "ignoreboth") == 0)
+               pset.histcontrol = hctl_ignoreboth;
+       else
+               pset.histcontrol = hctl_none;
+}
+
+static void
+prompt1_hook(const char *newval)
+{
+       pset.prompt1 = newval ? newval : "";
+}
+
+static void
+prompt2_hook(const char *newval)
+{
+       pset.prompt2 = newval ? newval : "";
+}
+
+static void
+prompt3_hook(const char *newval)
+{
+       pset.prompt3 = newval ? newval : "";
+}
+
+static void
+verbosity_hook(const char *newval)
+{
+       if (newval == NULL)
+               pset.verbosity = PQERRORS_DEFAULT;
+       else if (strcmp(newval, "default") == 0)
+               pset.verbosity = PQERRORS_DEFAULT;
+       else if (strcmp(newval, "terse") == 0)
+               pset.verbosity = PQERRORS_TERSE;
+       else if (strcmp(newval, "verbose") == 0)
+               pset.verbosity = PQERRORS_VERBOSE;
+       else
+               pset.verbosity = PQERRORS_DEFAULT;
+
+       if (pset.db)
+               PQsetErrorVerbosity(pset.db, pset.verbosity);
+}
+
+
+static void
+EstablishVariableSpace(void)
+{
+       pset.vars = CreateVariableSpace();
+
+       SetVariableAssignHook(pset.vars, "AUTOCOMMIT", autocommit_hook);
+       SetVariableAssignHook(pset.vars, "ON_ERROR_STOP", on_error_stop_hook);
+       SetVariableAssignHook(pset.vars, "QUIET", quiet_hook);
+       SetVariableAssignHook(pset.vars, "SINGLELINE", singleline_hook);
+       SetVariableAssignHook(pset.vars, "SINGLESTEP", singlestep_hook);
+       SetVariableAssignHook(pset.vars, "FETCH_COUNT", fetch_count_hook);
+       SetVariableAssignHook(pset.vars, "ECHO", echo_hook);
+       SetVariableAssignHook(pset.vars, "ECHO_HIDDEN", echo_hidden_hook);
+       SetVariableAssignHook(pset.vars, "ON_ERROR_ROLLBACK", on_error_rollback_hook);
+       SetVariableAssignHook(pset.vars, "HISTCONTROL", histcontrol_hook);
+       SetVariableAssignHook(pset.vars, "PROMPT1", prompt1_hook);
+       SetVariableAssignHook(pset.vars, "PROMPT2", prompt2_hook);
+       SetVariableAssignHook(pset.vars, "PROMPT3", prompt3_hook);
+       SetVariableAssignHook(pset.vars, "VERBOSITY", verbosity_hook);
+}