Header And Logo

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

startup.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/startup.c
00007  */
00008 #include "postgres_fe.h"
00009 
00010 #include <sys/types.h>
00011 
00012 #ifndef WIN32
00013 #include <unistd.h>
00014 #else                           /* WIN32 */
00015 #include <io.h>
00016 #include <win32.h>
00017 #endif   /* WIN32 */
00018 
00019 #include "getopt_long.h"
00020 
00021 #include <locale.h>
00022 
00023 #include "command.h"
00024 #include "common.h"
00025 #include "describe.h"
00026 #include "help.h"
00027 #include "input.h"
00028 #include "mainloop.h"
00029 #include "settings.h"
00030 
00031 
00032 
00033 /*
00034  * Global psql options
00035  */
00036 PsqlSettings pset;
00037 
00038 #ifndef WIN32
00039 #define SYSPSQLRC   "psqlrc"
00040 #define PSQLRC      ".psqlrc"
00041 #else
00042 #define SYSPSQLRC   "psqlrc"
00043 #define PSQLRC      "psqlrc.conf"
00044 #endif
00045 
00046 /*
00047  * Structures to pass information between the option parsing routine
00048  * and the main function
00049  */
00050 enum _actions
00051 {
00052     ACT_NOTHING = 0,
00053     ACT_SINGLE_SLASH,
00054     ACT_LIST_DB,
00055     ACT_SINGLE_QUERY,
00056     ACT_FILE
00057 };
00058 
00059 struct adhoc_opts
00060 {
00061     char       *dbname;
00062     char       *host;
00063     char       *port;
00064     char       *username;
00065     char       *logfilename;
00066     enum _actions action;
00067     char       *action_string;
00068     bool        no_readline;
00069     bool        no_psqlrc;
00070     bool        single_txn;
00071 };
00072 
00073 static void parse_psql_options(int argc, char *argv[],
00074                    struct adhoc_opts * options);
00075 static void process_psqlrc(char *argv0);
00076 static void process_psqlrc_file(char *filename);
00077 static void showVersion(void);
00078 static void EstablishVariableSpace(void);
00079 
00080 /*
00081  *
00082  * main
00083  *
00084  */
00085 int
00086 main(int argc, char *argv[])
00087 {
00088     struct adhoc_opts options;
00089     int         successResult;
00090     char       *password = NULL;
00091     char       *password_prompt = NULL;
00092     bool        new_pass;
00093 
00094     set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("psql"));
00095 
00096     if (argc > 1)
00097     {
00098         if (strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-?") == 0)
00099         {
00100             usage();
00101             exit(EXIT_SUCCESS);
00102         }
00103         if (strcmp(argv[1], "--version") == 0 || strcmp(argv[1], "-V") == 0)
00104         {
00105             showVersion();
00106             exit(EXIT_SUCCESS);
00107         }
00108     }
00109 
00110 #ifdef WIN32
00111     setvbuf(stderr, NULL, _IONBF, 0);
00112 #endif
00113 
00114     setup_cancel_handler();
00115 
00116     pset.progname = get_progname(argv[0]);
00117 
00118     pset.db = NULL;
00119     setDecimalLocale();
00120     pset.encoding = PQenv2encoding();
00121     pset.queryFout = stdout;
00122     pset.queryFoutPipe = false;
00123     pset.cur_cmd_source = stdin;
00124     pset.cur_cmd_interactive = false;
00125 
00126     /* We rely on unmentioned fields of pset.popt to start out 0/false/NULL */
00127     pset.popt.topt.format = PRINT_ALIGNED;
00128     pset.popt.topt.border = 1;
00129     pset.popt.topt.pager = 1;
00130     pset.popt.topt.start_table = true;
00131     pset.popt.topt.stop_table = true;
00132     pset.popt.topt.default_footer = true;
00133     /* We must get COLUMNS here before readline() sets it */
00134     pset.popt.topt.env_columns = getenv("COLUMNS") ? atoi(getenv("COLUMNS")) : 0;
00135 
00136     pset.notty = (!isatty(fileno(stdin)) || !isatty(fileno(stdout)));
00137 
00138     pset.getPassword = TRI_DEFAULT;
00139 
00140     EstablishVariableSpace();
00141 
00142     SetVariable(pset.vars, "VERSION", PG_VERSION_STR);
00143 
00144     /* Default values for variables */
00145     SetVariableBool(pset.vars, "AUTOCOMMIT");
00146     SetVariable(pset.vars, "VERBOSITY", "default");
00147     SetVariable(pset.vars, "PROMPT1", DEFAULT_PROMPT1);
00148     SetVariable(pset.vars, "PROMPT2", DEFAULT_PROMPT2);
00149     SetVariable(pset.vars, "PROMPT3", DEFAULT_PROMPT3);
00150 
00151     parse_psql_options(argc, argv, &options);
00152 
00153     /*
00154      * If no action was specified and we're in non-interactive mode, treat
00155      * it as if the user had specified "-f -".  This lets single-transaction
00156      * mode work in this case.
00157      */
00158     if (options.action == ACT_NOTHING && pset.notty)
00159     {
00160         options.action = ACT_FILE;
00161         options.action_string = NULL;
00162     }
00163 
00164     /* Bail out if -1 was specified but will be ignored. */
00165     if (options.single_txn && options.action != ACT_FILE)
00166     {
00167         if (options.action == ACT_NOTHING)
00168             fprintf(stderr,_("%s: -1 can only be used in non-interactive mode\n"), pset.progname);
00169         else
00170             fprintf(stderr,_("%s: -1 is incompatible with -c and -l\n"), pset.progname);
00171         exit(EXIT_FAILURE);
00172     }
00173 
00174     if (!pset.popt.topt.fieldSep.separator &&
00175         !pset.popt.topt.fieldSep.separator_zero)
00176     {
00177         pset.popt.topt.fieldSep.separator = pg_strdup(DEFAULT_FIELD_SEP);
00178         pset.popt.topt.fieldSep.separator_zero = false;
00179     }
00180     if (!pset.popt.topt.recordSep.separator &&
00181         !pset.popt.topt.recordSep.separator_zero)
00182     {
00183         pset.popt.topt.recordSep.separator = pg_strdup(DEFAULT_RECORD_SEP);
00184         pset.popt.topt.recordSep.separator_zero = false;
00185     }
00186 
00187     if (options.username == NULL)
00188         password_prompt = pg_strdup(_("Password: "));
00189     else
00190     {
00191         password_prompt = pg_malloc(strlen(_("Password for user %s: ")) - 2 +
00192                                     strlen(options.username) + 1);
00193         sprintf(password_prompt, _("Password for user %s: "),
00194                 options.username);
00195     }
00196 
00197     if (pset.getPassword == TRI_YES)
00198         password = simple_prompt(password_prompt, 100, false);
00199 
00200     /* loop until we have a password if requested by backend */
00201     do
00202     {
00203 #define PARAMS_ARRAY_SIZE   8
00204         const char **keywords = pg_malloc(PARAMS_ARRAY_SIZE * sizeof(*keywords));
00205         const char **values = pg_malloc(PARAMS_ARRAY_SIZE * sizeof(*values));
00206 
00207         keywords[0] = "host";
00208         values[0] = options.host;
00209         keywords[1] = "port";
00210         values[1] = options.port;
00211         keywords[2] = "user";
00212         values[2] = options.username;
00213         keywords[3] = "password";
00214         values[3] = password;
00215         keywords[4] = "dbname";
00216         values[4] = (options.action == ACT_LIST_DB &&
00217                      options.dbname == NULL) ?
00218             "postgres" : options.dbname;
00219         keywords[5] = "fallback_application_name";
00220         values[5] = pset.progname;
00221         keywords[6] = "client_encoding";
00222         values[6] = (pset.notty || getenv("PGCLIENTENCODING")) ? NULL : "auto";
00223         keywords[7] = NULL;
00224         values[7] = NULL;
00225 
00226         new_pass = false;
00227         pset.db = PQconnectdbParams(keywords, values, true);
00228         free(keywords);
00229         free(values);
00230 
00231         if (PQstatus(pset.db) == CONNECTION_BAD &&
00232             PQconnectionNeedsPassword(pset.db) &&
00233             password == NULL &&
00234             pset.getPassword != TRI_NO)
00235         {
00236             PQfinish(pset.db);
00237             password = simple_prompt(password_prompt, 100, false);
00238             new_pass = true;
00239         }
00240     } while (new_pass);
00241 
00242     free(password);
00243     free(password_prompt);
00244 
00245     if (PQstatus(pset.db) == CONNECTION_BAD)
00246     {
00247         fprintf(stderr, "%s: %s", pset.progname, PQerrorMessage(pset.db));
00248         PQfinish(pset.db);
00249         exit(EXIT_BADCONN);
00250     }
00251 
00252     PQsetNoticeProcessor(pset.db, NoticeProcessor, NULL);
00253 
00254     SyncVariables();
00255 
00256     if (options.action == ACT_LIST_DB)
00257     {
00258         int         success;
00259 
00260         if (!options.no_psqlrc)
00261             process_psqlrc(argv[0]);
00262 
00263         success = listAllDbs(NULL, false);
00264         PQfinish(pset.db);
00265         exit(success ? EXIT_SUCCESS : EXIT_FAILURE);
00266     }
00267 
00268     if (options.logfilename)
00269     {
00270         pset.logfile = fopen(options.logfilename, "a");
00271         if (!pset.logfile)
00272             fprintf(stderr, _("%s: could not open log file \"%s\": %s\n"),
00273                     pset.progname, options.logfilename, strerror(errno));
00274     }
00275 
00276     /*
00277      * Now find something to do
00278      */
00279 
00280     /*
00281      * process file given by -f
00282      */
00283     if (options.action == ACT_FILE)
00284     {
00285         if (!options.no_psqlrc)
00286             process_psqlrc(argv[0]);
00287 
00288         successResult = process_file(options.action_string, options.single_txn, false);
00289     }
00290 
00291     /*
00292      * process slash command if one was given to -c
00293      */
00294     else if (options.action == ACT_SINGLE_SLASH)
00295     {
00296         PsqlScanState scan_state;
00297 
00298         if (pset.echo == PSQL_ECHO_ALL)
00299             puts(options.action_string);
00300 
00301         scan_state = psql_scan_create();
00302         psql_scan_setup(scan_state,
00303                         options.action_string,
00304                         strlen(options.action_string));
00305 
00306         successResult = HandleSlashCmds(scan_state, NULL) != PSQL_CMD_ERROR
00307             ? EXIT_SUCCESS : EXIT_FAILURE;
00308 
00309         psql_scan_destroy(scan_state);
00310     }
00311 
00312     /*
00313      * If the query given to -c was a normal one, send it
00314      */
00315     else if (options.action == ACT_SINGLE_QUERY)
00316     {
00317         if (pset.echo == PSQL_ECHO_ALL)
00318             puts(options.action_string);
00319 
00320         successResult = SendQuery(options.action_string)
00321             ? EXIT_SUCCESS : EXIT_FAILURE;
00322     }
00323 
00324     /*
00325      * or otherwise enter interactive main loop
00326      */
00327     else
00328     {
00329         if (!options.no_psqlrc)
00330             process_psqlrc(argv[0]);
00331 
00332         connection_warnings(true);
00333         if (!pset.quiet)
00334             printf(_("Type \"help\" for help.\n\n"));
00335         initializeInput(options.no_readline ? 0 : 1);
00336         successResult = MainLoop(stdin);
00337     }
00338 
00339     /* clean up */
00340     if (pset.logfile)
00341         fclose(pset.logfile);
00342     PQfinish(pset.db);
00343     setQFout(NULL);
00344 
00345     return successResult;
00346 }
00347 
00348 
00349 /*
00350  * Parse command line options
00351  */
00352 
00353 static void
00354 parse_psql_options(int argc, char *argv[], struct adhoc_opts * options)
00355 {
00356     static struct option long_options[] =
00357     {
00358         {"echo-all", no_argument, NULL, 'a'},
00359         {"no-align", no_argument, NULL, 'A'},
00360         {"command", required_argument, NULL, 'c'},
00361         {"dbname", required_argument, NULL, 'd'},
00362         {"echo-queries", no_argument, NULL, 'e'},
00363         {"echo-hidden", no_argument, NULL, 'E'},
00364         {"file", required_argument, NULL, 'f'},
00365         {"field-separator", required_argument, NULL, 'F'},
00366         {"field-separator-zero", no_argument, NULL, 'z'},
00367         {"host", required_argument, NULL, 'h'},
00368         {"html", no_argument, NULL, 'H'},
00369         {"list", no_argument, NULL, 'l'},
00370         {"log-file", required_argument, NULL, 'L'},
00371         {"no-readline", no_argument, NULL, 'n'},
00372         {"single-transaction", no_argument, NULL, '1'},
00373         {"output", required_argument, NULL, 'o'},
00374         {"port", required_argument, NULL, 'p'},
00375         {"pset", required_argument, NULL, 'P'},
00376         {"quiet", no_argument, NULL, 'q'},
00377         {"record-separator", required_argument, NULL, 'R'},
00378         {"record-separator-zero", no_argument, NULL, '0'},
00379         {"single-step", no_argument, NULL, 's'},
00380         {"single-line", no_argument, NULL, 'S'},
00381         {"tuples-only", no_argument, NULL, 't'},
00382         {"table-attr", required_argument, NULL, 'T'},
00383         {"username", required_argument, NULL, 'U'},
00384         {"set", required_argument, NULL, 'v'},
00385         {"variable", required_argument, NULL, 'v'},
00386         {"version", no_argument, NULL, 'V'},
00387         {"no-password", no_argument, NULL, 'w'},
00388         {"password", no_argument, NULL, 'W'},
00389         {"expanded", no_argument, NULL, 'x'},
00390         {"no-psqlrc", no_argument, NULL, 'X'},
00391         {"help", no_argument, NULL, '?'},
00392         {NULL, 0, NULL, 0}
00393     };
00394 
00395     int         optindex;
00396     extern char *optarg;
00397     extern int  optind;
00398     int         c;
00399 
00400     memset(options, 0, sizeof *options);
00401 
00402     while ((c = getopt_long(argc, argv, "aAc:d:eEf:F:h:HlL:no:p:P:qR:sStT:U:v:VwWxXz?01",
00403                             long_options, &optindex)) != -1)
00404     {
00405         switch (c)
00406         {
00407             case 'a':
00408                 SetVariable(pset.vars, "ECHO", "all");
00409                 break;
00410             case 'A':
00411                 pset.popt.topt.format = PRINT_UNALIGNED;
00412                 break;
00413             case 'c':
00414                 options->action_string = pg_strdup(optarg);
00415                 if (optarg[0] == '\\')
00416                 {
00417                     options->action = ACT_SINGLE_SLASH;
00418                     options->action_string++;
00419                 }
00420                 else
00421                     options->action = ACT_SINGLE_QUERY;
00422                 break;
00423             case 'd':
00424                 options->dbname = pg_strdup(optarg);
00425                 break;
00426             case 'e':
00427                 SetVariable(pset.vars, "ECHO", "queries");
00428                 break;
00429             case 'E':
00430                 SetVariableBool(pset.vars, "ECHO_HIDDEN");
00431                 break;
00432             case 'f':
00433                 options->action = ACT_FILE;
00434                 options->action_string = pg_strdup(optarg);
00435                 break;
00436             case 'F':
00437                 pset.popt.topt.fieldSep.separator = pg_strdup(optarg);
00438                 pset.popt.topt.fieldSep.separator_zero = false;
00439                 break;
00440             case 'h':
00441                 options->host = pg_strdup(optarg);
00442                 break;
00443             case 'H':
00444                 pset.popt.topt.format = PRINT_HTML;
00445                 break;
00446             case 'l':
00447                 options->action = ACT_LIST_DB;
00448                 break;
00449             case 'L':
00450                 options->logfilename = pg_strdup(optarg);
00451                 break;
00452             case 'n':
00453                 options->no_readline = true;
00454                 break;
00455             case 'o':
00456                 setQFout(optarg);
00457                 break;
00458             case 'p':
00459                 options->port = pg_strdup(optarg);
00460                 break;
00461             case 'P':
00462                 {
00463                     char       *value;
00464                     char       *equal_loc;
00465                     bool        result;
00466 
00467                     value = pg_strdup(optarg);
00468                     equal_loc = strchr(value, '=');
00469                     if (!equal_loc)
00470                         result = do_pset(value, NULL, &pset.popt, true);
00471                     else
00472                     {
00473                         *equal_loc = '\0';
00474                         result = do_pset(value, equal_loc + 1, &pset.popt, true);
00475                     }
00476 
00477                     if (!result)
00478                     {
00479                         fprintf(stderr, _("%s: could not set printing parameter \"%s\"\n"), pset.progname, value);
00480                         exit(EXIT_FAILURE);
00481                     }
00482 
00483                     free(value);
00484                     break;
00485                 }
00486             case 'q':
00487                 SetVariableBool(pset.vars, "QUIET");
00488                 break;
00489             case 'R':
00490                 pset.popt.topt.recordSep.separator = pg_strdup(optarg);
00491                 pset.popt.topt.recordSep.separator_zero = false;
00492                 break;
00493             case 's':
00494                 SetVariableBool(pset.vars, "SINGLESTEP");
00495                 break;
00496             case 'S':
00497                 SetVariableBool(pset.vars, "SINGLELINE");
00498                 break;
00499             case 't':
00500                 pset.popt.topt.tuples_only = true;
00501                 break;
00502             case 'T':
00503                 pset.popt.topt.tableAttr = pg_strdup(optarg);
00504                 break;
00505             case 'U':
00506                 options->username = pg_strdup(optarg);
00507                 break;
00508             case 'v':
00509                 {
00510                     char       *value;
00511                     char       *equal_loc;
00512 
00513                     value = pg_strdup(optarg);
00514                     equal_loc = strchr(value, '=');
00515                     if (!equal_loc)
00516                     {
00517                         if (!DeleteVariable(pset.vars, value))
00518                         {
00519                             fprintf(stderr, _("%s: could not delete variable \"%s\"\n"),
00520                                     pset.progname, value);
00521                             exit(EXIT_FAILURE);
00522                         }
00523                     }
00524                     else
00525                     {
00526                         *equal_loc = '\0';
00527                         if (!SetVariable(pset.vars, value, equal_loc + 1))
00528                         {
00529                             fprintf(stderr, _("%s: could not set variable \"%s\"\n"),
00530                                     pset.progname, value);
00531                             exit(EXIT_FAILURE);
00532                         }
00533                     }
00534 
00535                     free(value);
00536                     break;
00537                 }
00538             case 'V':
00539                 showVersion();
00540                 exit(EXIT_SUCCESS);
00541             case 'w':
00542                 pset.getPassword = TRI_NO;
00543                 break;
00544             case 'W':
00545                 pset.getPassword = TRI_YES;
00546                 break;
00547             case 'x':
00548                 pset.popt.topt.expanded = true;
00549                 break;
00550             case 'X':
00551                 options->no_psqlrc = true;
00552                 break;
00553             case 'z':
00554                 pset.popt.topt.fieldSep.separator_zero = true;
00555                 break;
00556             case '0':
00557                 pset.popt.topt.recordSep.separator_zero = true;
00558                 break;
00559             case '1':
00560                 options->single_txn = true;
00561                 break;
00562             case '?':
00563                 /* Actual help option given */
00564                 if (strcmp(argv[optind - 1], "-?") == 0 || strcmp(argv[optind - 1], "--help") == 0)
00565                 {
00566                     usage();
00567                     exit(EXIT_SUCCESS);
00568                 }
00569                 /* unknown option reported by getopt */
00570                 else
00571                 {
00572                     fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
00573                             pset.progname);
00574                     exit(EXIT_FAILURE);
00575                 }
00576                 break;
00577             default:
00578                 fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
00579                         pset.progname);
00580                 exit(EXIT_FAILURE);
00581                 break;
00582         }
00583     }
00584 
00585     /*
00586      * if we still have arguments, use it as the database name and username
00587      */
00588     while (argc - optind >= 1)
00589     {
00590         if (!options->dbname)
00591             options->dbname = argv[optind];
00592         else if (!options->username)
00593             options->username = argv[optind];
00594         else if (!pset.quiet)
00595             fprintf(stderr, _("%s: warning: extra command-line argument \"%s\" ignored\n"),
00596                     pset.progname, argv[optind]);
00597 
00598         optind++;
00599     }
00600 }
00601 
00602 
00603 /*
00604  * Load .psqlrc file, if found.
00605  */
00606 static void
00607 process_psqlrc(char *argv0)
00608 {
00609     char        home[MAXPGPATH];
00610     char        rc_file[MAXPGPATH];
00611     char        my_exec_path[MAXPGPATH];
00612     char        etc_path[MAXPGPATH];
00613     char       *envrc = getenv("PSQLRC");
00614 
00615     find_my_exec(argv0, my_exec_path);
00616     get_etc_path(my_exec_path, etc_path);
00617 
00618     snprintf(rc_file, MAXPGPATH, "%s/%s", etc_path, SYSPSQLRC);
00619     process_psqlrc_file(rc_file);
00620 
00621     if (envrc != NULL && strlen(envrc) > 0)
00622     {
00623         /* might need to free() this */
00624         char *envrc_alloc = pstrdup(envrc);
00625 
00626         expand_tilde(&envrc_alloc);
00627         process_psqlrc_file(envrc_alloc);
00628     }
00629     else if (get_home_path(home))
00630     {
00631         snprintf(rc_file, MAXPGPATH, "%s/%s", home, PSQLRC);
00632         process_psqlrc_file(rc_file);
00633     }
00634 }
00635 
00636 
00637 
00638 static void
00639 process_psqlrc_file(char *filename)
00640 {
00641     char       *psqlrc_minor,
00642                *psqlrc_major;
00643 
00644 #if defined(WIN32) && (!defined(__MINGW32__))
00645 #define R_OK 4
00646 #endif
00647 
00648     psqlrc_minor = pg_malloc(strlen(filename) + 1 + strlen(PG_VERSION) + 1);
00649     sprintf(psqlrc_minor, "%s-%s", filename, PG_VERSION);
00650     psqlrc_major = pg_malloc(strlen(filename) + 1 + strlen(PG_MAJORVERSION) + 1);
00651     sprintf(psqlrc_major, "%s-%s", filename, PG_MAJORVERSION);
00652 
00653     /* check for minor version first, then major, then no version */
00654     if (access(psqlrc_minor, R_OK) == 0)
00655         (void) process_file(psqlrc_minor, false, false);
00656     else if (access(psqlrc_major, R_OK) == 0)
00657         (void) process_file(psqlrc_major, false, false);
00658     else if (access(filename, R_OK) == 0)
00659         (void) process_file(filename, false, false);
00660 
00661     free(psqlrc_minor);
00662     free(psqlrc_major);
00663 }
00664 
00665 
00666 
00667 /* showVersion
00668  *
00669  * This output format is intended to match GNU standards.
00670  */
00671 static void
00672 showVersion(void)
00673 {
00674     puts("psql (PostgreSQL) " PG_VERSION);
00675 }
00676 
00677 
00678 
00679 /*
00680  * Assign hooks for psql variables.
00681  *
00682  * This isn't an amazingly good place for them, but neither is anywhere else.
00683  */
00684 
00685 static void
00686 autocommit_hook(const char *newval)
00687 {
00688     pset.autocommit = ParseVariableBool(newval);
00689 }
00690 
00691 static void
00692 on_error_stop_hook(const char *newval)
00693 {
00694     pset.on_error_stop = ParseVariableBool(newval);
00695 }
00696 
00697 static void
00698 quiet_hook(const char *newval)
00699 {
00700     pset.quiet = ParseVariableBool(newval);
00701 }
00702 
00703 static void
00704 singleline_hook(const char *newval)
00705 {
00706     pset.singleline = ParseVariableBool(newval);
00707 }
00708 
00709 static void
00710 singlestep_hook(const char *newval)
00711 {
00712     pset.singlestep = ParseVariableBool(newval);
00713 }
00714 
00715 static void
00716 fetch_count_hook(const char *newval)
00717 {
00718     pset.fetch_count = ParseVariableNum(newval, -1, -1, false);
00719 }
00720 
00721 static void
00722 echo_hook(const char *newval)
00723 {
00724     if (newval == NULL)
00725         pset.echo = PSQL_ECHO_NONE;
00726     else if (strcmp(newval, "queries") == 0)
00727         pset.echo = PSQL_ECHO_QUERIES;
00728     else if (strcmp(newval, "all") == 0)
00729         pset.echo = PSQL_ECHO_ALL;
00730     else
00731         pset.echo = PSQL_ECHO_NONE;
00732 }
00733 
00734 static void
00735 echo_hidden_hook(const char *newval)
00736 {
00737     if (newval == NULL)
00738         pset.echo_hidden = PSQL_ECHO_HIDDEN_OFF;
00739     else if (strcmp(newval, "noexec") == 0)
00740         pset.echo_hidden = PSQL_ECHO_HIDDEN_NOEXEC;
00741     else if (pg_strcasecmp(newval, "off") == 0)
00742         pset.echo_hidden = PSQL_ECHO_HIDDEN_OFF;
00743     else
00744         pset.echo_hidden = PSQL_ECHO_HIDDEN_ON;
00745 }
00746 
00747 static void
00748 on_error_rollback_hook(const char *newval)
00749 {
00750     if (newval == NULL)
00751         pset.on_error_rollback = PSQL_ERROR_ROLLBACK_OFF;
00752     else if (pg_strcasecmp(newval, "interactive") == 0)
00753         pset.on_error_rollback = PSQL_ERROR_ROLLBACK_INTERACTIVE;
00754     else if (pg_strcasecmp(newval, "off") == 0)
00755         pset.on_error_rollback = PSQL_ERROR_ROLLBACK_OFF;
00756     else
00757         pset.on_error_rollback = PSQL_ERROR_ROLLBACK_ON;
00758 }
00759 
00760 static void
00761 histcontrol_hook(const char *newval)
00762 {
00763     if (newval == NULL)
00764         pset.histcontrol = hctl_none;
00765     else if (strcmp(newval, "ignorespace") == 0)
00766         pset.histcontrol = hctl_ignorespace;
00767     else if (strcmp(newval, "ignoredups") == 0)
00768         pset.histcontrol = hctl_ignoredups;
00769     else if (strcmp(newval, "ignoreboth") == 0)
00770         pset.histcontrol = hctl_ignoreboth;
00771     else
00772         pset.histcontrol = hctl_none;
00773 }
00774 
00775 static void
00776 prompt1_hook(const char *newval)
00777 {
00778     pset.prompt1 = newval ? newval : "";
00779 }
00780 
00781 static void
00782 prompt2_hook(const char *newval)
00783 {
00784     pset.prompt2 = newval ? newval : "";
00785 }
00786 
00787 static void
00788 prompt3_hook(const char *newval)
00789 {
00790     pset.prompt3 = newval ? newval : "";
00791 }
00792 
00793 static void
00794 verbosity_hook(const char *newval)
00795 {
00796     if (newval == NULL)
00797         pset.verbosity = PQERRORS_DEFAULT;
00798     else if (strcmp(newval, "default") == 0)
00799         pset.verbosity = PQERRORS_DEFAULT;
00800     else if (strcmp(newval, "terse") == 0)
00801         pset.verbosity = PQERRORS_TERSE;
00802     else if (strcmp(newval, "verbose") == 0)
00803         pset.verbosity = PQERRORS_VERBOSE;
00804     else
00805         pset.verbosity = PQERRORS_DEFAULT;
00806 
00807     if (pset.db)
00808         PQsetErrorVerbosity(pset.db, pset.verbosity);
00809 }
00810 
00811 
00812 static void
00813 EstablishVariableSpace(void)
00814 {
00815     pset.vars = CreateVariableSpace();
00816 
00817     SetVariableAssignHook(pset.vars, "AUTOCOMMIT", autocommit_hook);
00818     SetVariableAssignHook(pset.vars, "ON_ERROR_STOP", on_error_stop_hook);
00819     SetVariableAssignHook(pset.vars, "QUIET", quiet_hook);
00820     SetVariableAssignHook(pset.vars, "SINGLELINE", singleline_hook);
00821     SetVariableAssignHook(pset.vars, "SINGLESTEP", singlestep_hook);
00822     SetVariableAssignHook(pset.vars, "FETCH_COUNT", fetch_count_hook);
00823     SetVariableAssignHook(pset.vars, "ECHO", echo_hook);
00824     SetVariableAssignHook(pset.vars, "ECHO_HIDDEN", echo_hidden_hook);
00825     SetVariableAssignHook(pset.vars, "ON_ERROR_ROLLBACK", on_error_rollback_hook);
00826     SetVariableAssignHook(pset.vars, "HISTCONTROL", histcontrol_hook);
00827     SetVariableAssignHook(pset.vars, "PROMPT1", prompt1_hook);
00828     SetVariableAssignHook(pset.vars, "PROMPT2", prompt2_hook);
00829     SetVariableAssignHook(pset.vars, "PROMPT3", prompt3_hook);
00830     SetVariableAssignHook(pset.vars, "VERBOSITY", verbosity_hook);
00831 }