PageRenderTime 51ms CodeModel.GetById 25ms RepoModel.GetById 0ms app.codeStats 0ms

/src/bin/psql/startup.c

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