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