]> granicus.if.org Git - postgresql/blob - src/bin/psql/startup.c
Update copyright for 2014
[postgresql] / src / bin / psql / startup.c
1 /*
2  * psql - the PostgreSQL interactive terminal
3  *
4  * Copyright (c) 2000-2014, PostgreSQL Global Development Group
5  *
6  * src/bin/psql/startup.c
7  */
8 #include "postgres_fe.h"
9
10 #include <sys/types.h>
11
12 #ifndef WIN32
13 #include <unistd.h>
14 #else                                                   /* WIN32 */
15 #include <io.h>
16 #include <win32.h>
17 #endif   /* WIN32 */
18
19 #include "getopt_long.h"
20
21 #include <locale.h>
22
23 #include "command.h"
24 #include "common.h"
25 #include "describe.h"
26 #include "help.h"
27 #include "input.h"
28 #include "mainloop.h"
29 #include "settings.h"
30
31
32
33 /*
34  * Global psql options
35  */
36 PsqlSettings pset;
37
38 #ifndef WIN32
39 #define SYSPSQLRC       "psqlrc"
40 #define PSQLRC          ".psqlrc"
41 #else
42 #define SYSPSQLRC       "psqlrc"
43 #define PSQLRC          "psqlrc.conf"
44 #endif
45
46 /*
47  * Structures to pass information between the option parsing routine
48  * and the main function
49  */
50 enum _actions
51 {
52         ACT_NOTHING = 0,
53         ACT_SINGLE_SLASH,
54         ACT_LIST_DB,
55         ACT_SINGLE_QUERY,
56         ACT_FILE
57 };
58
59 struct adhoc_opts
60 {
61         char       *dbname;
62         char       *host;
63         char       *port;
64         char       *username;
65         char       *logfilename;
66         enum _actions action;
67         char       *action_string;
68         bool            no_readline;
69         bool            no_psqlrc;
70         bool            single_txn;
71 };
72
73 static void parse_psql_options(int argc, char *argv[],
74                                    struct adhoc_opts * options);
75 static void process_psqlrc(char *argv0);
76 static void process_psqlrc_file(char *filename);
77 static void showVersion(void);
78 static void EstablishVariableSpace(void);
79
80 /*
81  *
82  * main
83  *
84  */
85 int
86 main(int argc, char *argv[])
87 {
88         struct adhoc_opts options;
89         int                     successResult;
90         char       *password = NULL;
91         char       *password_prompt = NULL;
92         bool            new_pass;
93
94         set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("psql"));
95
96         if (argc > 1)
97         {
98                 if (strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-?") == 0)
99                 {
100                         usage();
101                         exit(EXIT_SUCCESS);
102                 }
103                 if (strcmp(argv[1], "--version") == 0 || strcmp(argv[1], "-V") == 0)
104                 {
105                         showVersion();
106                         exit(EXIT_SUCCESS);
107                 }
108         }
109
110 #ifdef WIN32
111         setvbuf(stderr, NULL, _IONBF, 0);
112 #endif
113
114         pset.progname = get_progname(argv[0]);
115
116         pset.db = NULL;
117         setDecimalLocale();
118         pset.encoding = PQenv2encoding();
119         pset.queryFout = stdout;
120         pset.queryFoutPipe = false;
121         pset.cur_cmd_source = stdin;
122         pset.cur_cmd_interactive = false;
123
124         /* We rely on unmentioned fields of pset.popt to start out 0/false/NULL */
125         pset.popt.topt.format = PRINT_ALIGNED;
126         pset.popt.topt.border = 1;
127         pset.popt.topt.pager = 1;
128         pset.popt.topt.start_table = true;
129         pset.popt.topt.stop_table = true;
130         pset.popt.topt.default_footer = true;
131         /* We must get COLUMNS here before readline() sets it */
132         pset.popt.topt.env_columns = getenv("COLUMNS") ? atoi(getenv("COLUMNS")) : 0;
133
134         pset.notty = (!isatty(fileno(stdin)) || !isatty(fileno(stdout)));
135
136         pset.getPassword = TRI_DEFAULT;
137
138         EstablishVariableSpace();
139
140         SetVariable(pset.vars, "VERSION", PG_VERSION_STR);
141
142         /* Default values for variables */
143         SetVariableBool(pset.vars, "AUTOCOMMIT");
144         SetVariable(pset.vars, "VERBOSITY", "default");
145         SetVariable(pset.vars, "PROMPT1", DEFAULT_PROMPT1);
146         SetVariable(pset.vars, "PROMPT2", DEFAULT_PROMPT2);
147         SetVariable(pset.vars, "PROMPT3", DEFAULT_PROMPT3);
148
149         parse_psql_options(argc, argv, &options);
150
151         /*
152          * If no action was specified and we're in non-interactive mode, treat it
153          * as if the user had specified "-f -".  This lets single-transaction mode
154          * work in this case.
155          */
156         if (options.action == ACT_NOTHING && pset.notty)
157         {
158                 options.action = ACT_FILE;
159                 options.action_string = NULL;
160         }
161
162         /* Bail out if -1 was specified but will be ignored. */
163         if (options.single_txn && options.action != ACT_FILE && options.action == ACT_NOTHING)
164         {
165                 fprintf(stderr, _("%s: -1 can only be used in non-interactive mode\n"), pset.progname);
166                 exit(EXIT_FAILURE);
167         }
168
169         if (!pset.popt.topt.fieldSep.separator &&
170                 !pset.popt.topt.fieldSep.separator_zero)
171         {
172                 pset.popt.topt.fieldSep.separator = pg_strdup(DEFAULT_FIELD_SEP);
173                 pset.popt.topt.fieldSep.separator_zero = false;
174         }
175         if (!pset.popt.topt.recordSep.separator &&
176                 !pset.popt.topt.recordSep.separator_zero)
177         {
178                 pset.popt.topt.recordSep.separator = pg_strdup(DEFAULT_RECORD_SEP);
179                 pset.popt.topt.recordSep.separator_zero = false;
180         }
181
182         if (options.username == NULL)
183                 password_prompt = pg_strdup(_("Password: "));
184         else
185                 password_prompt = psprintf(_("Password for user %s: "),
186                                                                    options.username);
187
188         if (pset.getPassword == TRI_YES)
189                 password = simple_prompt(password_prompt, 100, false);
190
191         /* loop until we have a password if requested by backend */
192         do
193         {
194 #define PARAMS_ARRAY_SIZE       8
195                 const char **keywords = pg_malloc(PARAMS_ARRAY_SIZE * sizeof(*keywords));
196                 const char **values = pg_malloc(PARAMS_ARRAY_SIZE * sizeof(*values));
197
198                 keywords[0] = "host";
199                 values[0] = options.host;
200                 keywords[1] = "port";
201                 values[1] = options.port;
202                 keywords[2] = "user";
203                 values[2] = options.username;
204                 keywords[3] = "password";
205                 values[3] = password;
206                 keywords[4] = "dbname";
207                 values[4] = (options.action == ACT_LIST_DB &&
208                                          options.dbname == NULL) ?
209                         "postgres" : options.dbname;
210                 keywords[5] = "fallback_application_name";
211                 values[5] = pset.progname;
212                 keywords[6] = "client_encoding";
213                 values[6] = (pset.notty || getenv("PGCLIENTENCODING")) ? NULL : "auto";
214                 keywords[7] = NULL;
215                 values[7] = NULL;
216
217                 new_pass = false;
218                 pset.db = PQconnectdbParams(keywords, values, true);
219                 free(keywords);
220                 free(values);
221
222                 if (PQstatus(pset.db) == CONNECTION_BAD &&
223                         PQconnectionNeedsPassword(pset.db) &&
224                         password == NULL &&
225                         pset.getPassword != TRI_NO)
226                 {
227                         PQfinish(pset.db);
228                         password = simple_prompt(password_prompt, 100, false);
229                         new_pass = true;
230                 }
231         } while (new_pass);
232
233         free(password);
234         free(password_prompt);
235
236         if (PQstatus(pset.db) == CONNECTION_BAD)
237         {
238                 fprintf(stderr, "%s: %s", pset.progname, PQerrorMessage(pset.db));
239                 PQfinish(pset.db);
240                 exit(EXIT_BADCONN);
241         }
242
243         setup_cancel_handler();
244
245         PQsetNoticeProcessor(pset.db, NoticeProcessor, NULL);
246
247         SyncVariables();
248
249         if (options.action == ACT_LIST_DB)
250         {
251                 int                     success;
252
253                 if (!options.no_psqlrc)
254                         process_psqlrc(argv[0]);
255
256                 success = listAllDbs(NULL, false);
257                 PQfinish(pset.db);
258                 exit(success ? EXIT_SUCCESS : EXIT_FAILURE);
259         }
260
261         if (options.logfilename)
262         {
263                 pset.logfile = fopen(options.logfilename, "a");
264                 if (!pset.logfile)
265                         fprintf(stderr, _("%s: could not open log file \"%s\": %s\n"),
266                                         pset.progname, options.logfilename, strerror(errno));
267         }
268
269         /*
270          * Now find something to do
271          */
272
273         /*
274          * process file given by -f
275          */
276         if (options.action == ACT_FILE)
277         {
278                 if (!options.no_psqlrc)
279                         process_psqlrc(argv[0]);
280
281                 successResult = process_file(options.action_string, options.single_txn, false);
282         }
283
284         /*
285          * process slash command if one was given to -c
286          */
287         else if (options.action == ACT_SINGLE_SLASH)
288         {
289                 PsqlScanState scan_state;
290
291                 if (pset.echo == PSQL_ECHO_ALL)
292                         puts(options.action_string);
293
294                 scan_state = psql_scan_create();
295                 psql_scan_setup(scan_state,
296                                                 options.action_string,
297                                                 strlen(options.action_string));
298
299                 successResult = HandleSlashCmds(scan_state, NULL) != PSQL_CMD_ERROR
300                         ? EXIT_SUCCESS : EXIT_FAILURE;
301
302                 psql_scan_destroy(scan_state);
303         }
304
305         /*
306          * If the query given to -c was a normal one, send it
307          */
308         else if (options.action == ACT_SINGLE_QUERY)
309         {
310                 if (pset.echo == PSQL_ECHO_ALL)
311                         puts(options.action_string);
312
313                 successResult = SendQuery(options.action_string)
314                         ? EXIT_SUCCESS : EXIT_FAILURE;
315         }
316
317         /*
318          * or otherwise enter interactive main loop
319          */
320         else
321         {
322                 if (!options.no_psqlrc)
323                         process_psqlrc(argv[0]);
324
325                 connection_warnings(true);
326                 if (!pset.quiet)
327                         printf(_("Type \"help\" for help.\n\n"));
328                 initializeInput(options.no_readline ? 0 : 1);
329                 successResult = MainLoop(stdin);
330         }
331
332         /* clean up */
333         if (pset.logfile)
334                 fclose(pset.logfile);
335         PQfinish(pset.db);
336         setQFout(NULL);
337
338         return successResult;
339 }
340
341
342 /*
343  * Parse command line options
344  */
345
346 static void
347 parse_psql_options(int argc, char *argv[], struct adhoc_opts * options)
348 {
349         static struct option long_options[] =
350         {
351                 {"echo-all", no_argument, NULL, 'a'},
352                 {"no-align", no_argument, NULL, 'A'},
353                 {"command", required_argument, NULL, 'c'},
354                 {"dbname", required_argument, NULL, 'd'},
355                 {"echo-queries", no_argument, NULL, 'e'},
356                 {"echo-hidden", no_argument, NULL, 'E'},
357                 {"file", required_argument, NULL, 'f'},
358                 {"field-separator", required_argument, NULL, 'F'},
359                 {"field-separator-zero", no_argument, NULL, 'z'},
360                 {"host", required_argument, NULL, 'h'},
361                 {"html", no_argument, NULL, 'H'},
362                 {"list", no_argument, NULL, 'l'},
363                 {"log-file", required_argument, NULL, 'L'},
364                 {"no-readline", no_argument, NULL, 'n'},
365                 {"single-transaction", no_argument, NULL, '1'},
366                 {"output", required_argument, NULL, 'o'},
367                 {"port", required_argument, NULL, 'p'},
368                 {"pset", required_argument, NULL, 'P'},
369                 {"quiet", no_argument, NULL, 'q'},
370                 {"record-separator", required_argument, NULL, 'R'},
371                 {"record-separator-zero", no_argument, NULL, '0'},
372                 {"single-step", no_argument, NULL, 's'},
373                 {"single-line", no_argument, NULL, 'S'},
374                 {"tuples-only", no_argument, NULL, 't'},
375                 {"table-attr", required_argument, NULL, 'T'},
376                 {"username", required_argument, NULL, 'U'},
377                 {"set", required_argument, NULL, 'v'},
378                 {"variable", required_argument, NULL, 'v'},
379                 {"version", no_argument, NULL, 'V'},
380                 {"no-password", no_argument, NULL, 'w'},
381                 {"password", no_argument, NULL, 'W'},
382                 {"expanded", no_argument, NULL, 'x'},
383                 {"no-psqlrc", no_argument, NULL, 'X'},
384                 {"help", no_argument, NULL, '?'},
385                 {NULL, 0, NULL, 0}
386         };
387
388         int                     optindex;
389         extern char *optarg;
390         extern int      optind;
391         int                     c;
392
393         memset(options, 0, sizeof *options);
394
395         while ((c = getopt_long(argc, argv, "aAc:d:eEf:F:h:HlL:no:p:P:qR:sStT:U:v:VwWxXz?01",
396                                                         long_options, &optindex)) != -1)
397         {
398                 switch (c)
399                 {
400                         case 'a':
401                                 SetVariable(pset.vars, "ECHO", "all");
402                                 break;
403                         case 'A':
404                                 pset.popt.topt.format = PRINT_UNALIGNED;
405                                 break;
406                         case 'c':
407                                 options->action_string = pg_strdup(optarg);
408                                 if (optarg[0] == '\\')
409                                 {
410                                         options->action = ACT_SINGLE_SLASH;
411                                         options->action_string++;
412                                 }
413                                 else
414                                         options->action = ACT_SINGLE_QUERY;
415                                 break;
416                         case 'd':
417                                 options->dbname = pg_strdup(optarg);
418                                 break;
419                         case 'e':
420                                 SetVariable(pset.vars, "ECHO", "queries");
421                                 break;
422                         case 'E':
423                                 SetVariableBool(pset.vars, "ECHO_HIDDEN");
424                                 break;
425                         case 'f':
426                                 options->action = ACT_FILE;
427                                 options->action_string = pg_strdup(optarg);
428                                 break;
429                         case 'F':
430                                 pset.popt.topt.fieldSep.separator = pg_strdup(optarg);
431                                 pset.popt.topt.fieldSep.separator_zero = false;
432                                 break;
433                         case 'h':
434                                 options->host = pg_strdup(optarg);
435                                 break;
436                         case 'H':
437                                 pset.popt.topt.format = PRINT_HTML;
438                                 break;
439                         case 'l':
440                                 options->action = ACT_LIST_DB;
441                                 break;
442                         case 'L':
443                                 options->logfilename = pg_strdup(optarg);
444                                 break;
445                         case 'n':
446                                 options->no_readline = true;
447                                 break;
448                         case 'o':
449                                 setQFout(optarg);
450                                 break;
451                         case 'p':
452                                 options->port = pg_strdup(optarg);
453                                 break;
454                         case 'P':
455                                 {
456                                         char       *value;
457                                         char       *equal_loc;
458                                         bool            result;
459
460                                         value = pg_strdup(optarg);
461                                         equal_loc = strchr(value, '=');
462                                         if (!equal_loc)
463                                                 result = do_pset(value, NULL, &pset.popt, true);
464                                         else
465                                         {
466                                                 *equal_loc = '\0';
467                                                 result = do_pset(value, equal_loc + 1, &pset.popt, true);
468                                         }
469
470                                         if (!result)
471                                         {
472                                                 fprintf(stderr, _("%s: could not set printing parameter \"%s\"\n"), pset.progname, value);
473                                                 exit(EXIT_FAILURE);
474                                         }
475
476                                         free(value);
477                                         break;
478                                 }
479                         case 'q':
480                                 SetVariableBool(pset.vars, "QUIET");
481                                 break;
482                         case 'R':
483                                 pset.popt.topt.recordSep.separator = pg_strdup(optarg);
484                                 pset.popt.topt.recordSep.separator_zero = false;
485                                 break;
486                         case 's':
487                                 SetVariableBool(pset.vars, "SINGLESTEP");
488                                 break;
489                         case 'S':
490                                 SetVariableBool(pset.vars, "SINGLELINE");
491                                 break;
492                         case 't':
493                                 pset.popt.topt.tuples_only = true;
494                                 break;
495                         case 'T':
496                                 pset.popt.topt.tableAttr = pg_strdup(optarg);
497                                 break;
498                         case 'U':
499                                 options->username = pg_strdup(optarg);
500                                 break;
501                         case 'v':
502                                 {
503                                         char       *value;
504                                         char       *equal_loc;
505
506                                         value = pg_strdup(optarg);
507                                         equal_loc = strchr(value, '=');
508                                         if (!equal_loc)
509                                         {
510                                                 if (!DeleteVariable(pset.vars, value))
511                                                 {
512                                                         fprintf(stderr, _("%s: could not delete variable \"%s\"\n"),
513                                                                         pset.progname, value);
514                                                         exit(EXIT_FAILURE);
515                                                 }
516                                         }
517                                         else
518                                         {
519                                                 *equal_loc = '\0';
520                                                 if (!SetVariable(pset.vars, value, equal_loc + 1))
521                                                 {
522                                                         fprintf(stderr, _("%s: could not set variable \"%s\"\n"),
523                                                                         pset.progname, value);
524                                                         exit(EXIT_FAILURE);
525                                                 }
526                                         }
527
528                                         free(value);
529                                         break;
530                                 }
531                         case 'V':
532                                 showVersion();
533                                 exit(EXIT_SUCCESS);
534                         case 'w':
535                                 pset.getPassword = TRI_NO;
536                                 break;
537                         case 'W':
538                                 pset.getPassword = TRI_YES;
539                                 break;
540                         case 'x':
541                                 pset.popt.topt.expanded = true;
542                                 break;
543                         case 'X':
544                                 options->no_psqlrc = true;
545                                 break;
546                         case 'z':
547                                 pset.popt.topt.fieldSep.separator_zero = true;
548                                 break;
549                         case '0':
550                                 pset.popt.topt.recordSep.separator_zero = true;
551                                 break;
552                         case '1':
553                                 options->single_txn = true;
554                                 break;
555                         case '?':
556                                 /* Actual help option given */
557                                 if (strcmp(argv[optind - 1], "--help") == 0 || strcmp(argv[optind - 1], "-?") == 0)
558                                 {
559                                         usage();
560                                         exit(EXIT_SUCCESS);
561                                 }
562                                 /* unknown option reported by getopt */
563                                 else
564                                 {
565                                         fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
566                                                         pset.progname);
567                                         exit(EXIT_FAILURE);
568                                 }
569                                 break;
570                         default:
571                                 fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
572                                                 pset.progname);
573                                 exit(EXIT_FAILURE);
574                                 break;
575                 }
576         }
577
578         /*
579          * if we still have arguments, use it as the database name and username
580          */
581         while (argc - optind >= 1)
582         {
583                 if (!options->dbname)
584                         options->dbname = argv[optind];
585                 else if (!options->username)
586                         options->username = argv[optind];
587                 else if (!pset.quiet)
588                         fprintf(stderr, _("%s: warning: extra command-line argument \"%s\" ignored\n"),
589                                         pset.progname, argv[optind]);
590
591                 optind++;
592         }
593 }
594
595
596 /*
597  * Load .psqlrc file, if found.
598  */
599 static void
600 process_psqlrc(char *argv0)
601 {
602         char            home[MAXPGPATH];
603         char            rc_file[MAXPGPATH];
604         char            my_exec_path[MAXPGPATH];
605         char            etc_path[MAXPGPATH];
606         char       *envrc = getenv("PSQLRC");
607
608         find_my_exec(argv0, my_exec_path);
609         get_etc_path(my_exec_path, etc_path);
610
611         snprintf(rc_file, MAXPGPATH, "%s/%s", etc_path, SYSPSQLRC);
612         process_psqlrc_file(rc_file);
613
614         if (envrc != NULL && strlen(envrc) > 0)
615         {
616                 /* might need to free() this */
617                 char       *envrc_alloc = pstrdup(envrc);
618
619                 expand_tilde(&envrc_alloc);
620                 process_psqlrc_file(envrc_alloc);
621         }
622         else if (get_home_path(home))
623         {
624                 snprintf(rc_file, MAXPGPATH, "%s/%s", home, PSQLRC);
625                 process_psqlrc_file(rc_file);
626         }
627 }
628
629
630
631 static void
632 process_psqlrc_file(char *filename)
633 {
634         char       *psqlrc_minor,
635                            *psqlrc_major;
636
637 #if defined(WIN32) && (!defined(__MINGW32__))
638 #define R_OK 4
639 #endif
640
641         psqlrc_minor = psprintf("%s-%s", filename, PG_VERSION);
642         psqlrc_major = psprintf("%s-%s", filename, PG_MAJORVERSION);
643
644         /* check for minor version first, then major, then no version */
645         if (access(psqlrc_minor, R_OK) == 0)
646                 (void) process_file(psqlrc_minor, false, false);
647         else if (access(psqlrc_major, R_OK) == 0)
648                 (void) process_file(psqlrc_major, false, false);
649         else if (access(filename, R_OK) == 0)
650                 (void) process_file(filename, false, false);
651
652         free(psqlrc_minor);
653         free(psqlrc_major);
654 }
655
656
657
658 /* showVersion
659  *
660  * This output format is intended to match GNU standards.
661  */
662 static void
663 showVersion(void)
664 {
665         puts("psql (PostgreSQL) " PG_VERSION);
666 }
667
668
669
670 /*
671  * Assign hooks for psql variables.
672  *
673  * This isn't an amazingly good place for them, but neither is anywhere else.
674  */
675
676 static void
677 autocommit_hook(const char *newval)
678 {
679         pset.autocommit = ParseVariableBool(newval);
680 }
681
682 static void
683 on_error_stop_hook(const char *newval)
684 {
685         pset.on_error_stop = ParseVariableBool(newval);
686 }
687
688 static void
689 quiet_hook(const char *newval)
690 {
691         pset.quiet = ParseVariableBool(newval);
692 }
693
694 static void
695 singleline_hook(const char *newval)
696 {
697         pset.singleline = ParseVariableBool(newval);
698 }
699
700 static void
701 singlestep_hook(const char *newval)
702 {
703         pset.singlestep = ParseVariableBool(newval);
704 }
705
706 static void
707 fetch_count_hook(const char *newval)
708 {
709         pset.fetch_count = ParseVariableNum(newval, -1, -1, false);
710 }
711
712 static void
713 echo_hook(const char *newval)
714 {
715         if (newval == NULL)
716                 pset.echo = PSQL_ECHO_NONE;
717         else if (strcmp(newval, "queries") == 0)
718                 pset.echo = PSQL_ECHO_QUERIES;
719         else if (strcmp(newval, "all") == 0)
720                 pset.echo = PSQL_ECHO_ALL;
721         else
722                 pset.echo = PSQL_ECHO_NONE;
723 }
724
725 static void
726 echo_hidden_hook(const char *newval)
727 {
728         if (newval == NULL)
729                 pset.echo_hidden = PSQL_ECHO_HIDDEN_OFF;
730         else if (strcmp(newval, "noexec") == 0)
731                 pset.echo_hidden = PSQL_ECHO_HIDDEN_NOEXEC;
732         else if (pg_strcasecmp(newval, "off") == 0)
733                 pset.echo_hidden = PSQL_ECHO_HIDDEN_OFF;
734         else
735                 pset.echo_hidden = PSQL_ECHO_HIDDEN_ON;
736 }
737
738 static void
739 on_error_rollback_hook(const char *newval)
740 {
741         if (newval == NULL)
742                 pset.on_error_rollback = PSQL_ERROR_ROLLBACK_OFF;
743         else if (pg_strcasecmp(newval, "interactive") == 0)
744                 pset.on_error_rollback = PSQL_ERROR_ROLLBACK_INTERACTIVE;
745         else if (pg_strcasecmp(newval, "off") == 0)
746                 pset.on_error_rollback = PSQL_ERROR_ROLLBACK_OFF;
747         else
748                 pset.on_error_rollback = PSQL_ERROR_ROLLBACK_ON;
749 }
750
751 static void
752 histcontrol_hook(const char *newval)
753 {
754         if (newval == NULL)
755                 pset.histcontrol = hctl_none;
756         else if (strcmp(newval, "ignorespace") == 0)
757                 pset.histcontrol = hctl_ignorespace;
758         else if (strcmp(newval, "ignoredups") == 0)
759                 pset.histcontrol = hctl_ignoredups;
760         else if (strcmp(newval, "ignoreboth") == 0)
761                 pset.histcontrol = hctl_ignoreboth;
762         else
763                 pset.histcontrol = hctl_none;
764 }
765
766 static void
767 prompt1_hook(const char *newval)
768 {
769         pset.prompt1 = newval ? newval : "";
770 }
771
772 static void
773 prompt2_hook(const char *newval)
774 {
775         pset.prompt2 = newval ? newval : "";
776 }
777
778 static void
779 prompt3_hook(const char *newval)
780 {
781         pset.prompt3 = newval ? newval : "";
782 }
783
784 static void
785 verbosity_hook(const char *newval)
786 {
787         if (newval == NULL)
788                 pset.verbosity = PQERRORS_DEFAULT;
789         else if (strcmp(newval, "default") == 0)
790                 pset.verbosity = PQERRORS_DEFAULT;
791         else if (strcmp(newval, "terse") == 0)
792                 pset.verbosity = PQERRORS_TERSE;
793         else if (strcmp(newval, "verbose") == 0)
794                 pset.verbosity = PQERRORS_VERBOSE;
795         else
796                 pset.verbosity = PQERRORS_DEFAULT;
797
798         if (pset.db)
799                 PQsetErrorVerbosity(pset.db, pset.verbosity);
800 }
801
802
803 static void
804 EstablishVariableSpace(void)
805 {
806         pset.vars = CreateVariableSpace();
807
808         SetVariableAssignHook(pset.vars, "AUTOCOMMIT", autocommit_hook);
809         SetVariableAssignHook(pset.vars, "ON_ERROR_STOP", on_error_stop_hook);
810         SetVariableAssignHook(pset.vars, "QUIET", quiet_hook);
811         SetVariableAssignHook(pset.vars, "SINGLELINE", singleline_hook);
812         SetVariableAssignHook(pset.vars, "SINGLESTEP", singlestep_hook);
813         SetVariableAssignHook(pset.vars, "FETCH_COUNT", fetch_count_hook);
814         SetVariableAssignHook(pset.vars, "ECHO", echo_hook);
815         SetVariableAssignHook(pset.vars, "ECHO_HIDDEN", echo_hidden_hook);
816         SetVariableAssignHook(pset.vars, "ON_ERROR_ROLLBACK", on_error_rollback_hook);
817         SetVariableAssignHook(pset.vars, "HISTCONTROL", histcontrol_hook);
818         SetVariableAssignHook(pset.vars, "PROMPT1", prompt1_hook);
819         SetVariableAssignHook(pset.vars, "PROMPT2", prompt2_hook);
820         SetVariableAssignHook(pset.vars, "PROMPT3", prompt3_hook);
821         SetVariableAssignHook(pset.vars, "VERBOSITY", verbosity_hook);
822 }