2 * psql - the PostgreSQL interactive terminal
4 * Copyright (c) 2000-2003, PostgreSQL Global Development Group
6 * $PostgreSQL: pgsql/src/bin/psql/startup.c,v 1.92 2004/05/02 04:25:45 momjian Exp $
8 #include "postgres_fe.h"
10 #include <sys/types.h>
20 #include "getopt_long.h"
38 #include "variables.h"
40 #include "mb/pg_wchar.h"
47 #define SYSPSQLRC "psqlrc"
48 #define PSQLRC ".psqlrc"
51 * Structures to pass information between the option parsing routine
52 * and the main function
75 static void parse_psql_options(int argc, char *argv[],
76 struct adhoc_opts * options);
77 static void process_psqlrc(void);
78 static void process_psqlrc_file(char *filename);
79 static void showVersion(void);
82 static void printSSLInfo(void);
87 checkWin32Codepage(void);
96 main(int argc, char *argv[])
98 struct adhoc_opts options;
101 char *username = NULL;
102 char *password = NULL;
105 setlocale(LC_ALL, "");
107 bindtextdomain("psql", LOCALEDIR);
111 pset.progname = get_progname(argv[0]);
115 if (strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-?") == 0)
120 if (strcmp(argv[1], "--version") == 0 || strcmp(argv[1], "-V") == 0)
128 setvbuf(stderr,NULL,_IONBF,0);
130 pset.cur_cmd_source = stdin;
131 pset.cur_cmd_interactive = false;
132 pset.encoding = PQenv2encoding();
134 pset.vars = CreateVariableSpace();
137 fprintf(stderr, gettext("%s: out of memory\n"), pset.progname);
140 pset.popt.topt.format = PRINT_ALIGNED;
141 pset.queryFout = stdout;
142 pset.popt.topt.border = 1;
143 pset.popt.topt.pager = 1;
144 pset.popt.default_footer = true;
146 SetVariable(pset.vars, "VERSION", PG_VERSION_STR);
148 /* Default values for variables that are used in noninteractive cases */
149 SetVariableBool(pset.vars, "AUTOCOMMIT");
150 SetVariable(pset.vars, "VERBOSITY", "default");
151 pset.verbosity = PQERRORS_DEFAULT;
153 pset.notty = (!isatty(fileno(stdin)) || !isatty(fileno(stdout)));
155 /* This is obsolete and should be removed sometime. */
156 #ifdef PSQL_ALWAYS_GET_PASSWORDS
157 pset.getPassword = true;
159 pset.getPassword = false;
162 #ifndef HAVE_UNIX_SOCKETS
163 /* default to localhost on platforms without unix sockets */
164 options.host = "localhost";
167 parse_psql_options(argc, argv, &options);
169 if (!pset.popt.topt.fieldSep)
170 pset.popt.topt.fieldSep = pg_strdup(DEFAULT_FIELD_SEP);
171 if (!pset.popt.topt.recordSep)
172 pset.popt.topt.recordSep = pg_strdup(DEFAULT_RECORD_SEP);
174 if (options.username)
177 * The \001 is a hack to support the deprecated -u option which
178 * issues a username prompt. The recommended option is -U followed
179 * by the name on the command line.
181 if (strcmp(options.username, "\001") == 0)
182 username = simple_prompt("User name: ", 100, true);
184 username = pg_strdup(options.username);
187 if (pset.getPassword)
188 password = simple_prompt("Password: ", 100, false);
190 /* loop until we have a password if requested by backend */
194 pset.db = PQsetdbLogin(options.host, options.port, NULL, NULL,
195 options.action == ACT_LIST_DB ? "template1" : options.dbname,
198 if (PQstatus(pset.db) == CONNECTION_BAD &&
199 strcmp(PQerrorMessage(pset.db), "fe_sendauth: no password supplied\n") == 0 &&
206 password = simple_prompt("Password: ", 100, false);
213 if (PQstatus(pset.db) == CONNECTION_BAD)
215 fprintf(stderr, "%s: %s", pset.progname, PQerrorMessage(pset.db));
220 PQsetNoticeProcessor(pset.db, NoticeProcessor, NULL);
224 if (options.action == ACT_LIST_DB)
226 int success = listAllDbs(false);
229 exit(success ? EXIT_SUCCESS : EXIT_FAILURE);
233 * Now find something to do
237 * process file given by -f
239 if (options.action == ACT_FILE && strcmp(options.action_string, "-") != 0)
241 if (!options.no_psqlrc)
244 successResult = process_file(options.action_string);
248 * process slash command if one was given to -c
250 else if (options.action == ACT_SINGLE_SLASH)
252 PsqlScanState scan_state;
254 if (VariableEquals(pset.vars, "ECHO", "all"))
255 puts(options.action_string);
257 scan_state = psql_scan_create();
258 psql_scan_setup(scan_state,
259 options.action_string,
260 strlen(options.action_string));
262 successResult = HandleSlashCmds(scan_state, NULL) != CMD_ERROR
263 ? EXIT_SUCCESS : EXIT_FAILURE;
265 psql_scan_destroy(scan_state);
269 * If the query given to -c was a normal one, send it
271 else if (options.action == ACT_SINGLE_QUERY)
273 if (VariableEquals(pset.vars, "ECHO", "all"))
274 puts(options.action_string);
276 successResult = SendQuery(options.action_string)
277 ? EXIT_SUCCESS : EXIT_FAILURE;
281 * or otherwise enter interactive main loop
285 if (!QUIET() && !pset.notty)
287 printf(gettext("Welcome to %s %s, the PostgreSQL interactive terminal.\n\n"
288 "Type: \\copyright for distribution terms\n"
289 " \\h for help with SQL commands\n"
290 " \\? for help with psql commands\n"
291 " \\g or terminate with semicolon to execute query\n"
293 pset.progname, PG_VERSION);
298 checkWin32Codepage();
302 /* Default values for variables that are used in interactive case */
303 SetVariable(pset.vars, "PROMPT1", DEFAULT_PROMPT1);
304 SetVariable(pset.vars, "PROMPT2", DEFAULT_PROMPT2);
305 SetVariable(pset.vars, "PROMPT3", DEFAULT_PROMPT3);
307 if (!options.no_psqlrc)
310 initializeInput(options.no_readline ? 0 : 1);
311 if (options.action_string) /* -f - was used */
312 pset.inputfile = "<stdin>";
314 successResult = MainLoop(stdin);
321 return successResult;
327 * Parse command line options
331 parse_psql_options(int argc, char *argv[], struct adhoc_opts * options)
333 static struct option long_options[] =
335 {"echo-all", no_argument, NULL, 'a'},
336 {"no-align", no_argument, NULL, 'A'},
337 {"command", required_argument, NULL, 'c'},
338 {"dbname", required_argument, NULL, 'd'},
339 {"echo-queries", no_argument, NULL, 'e'},
340 {"echo-hidden", no_argument, NULL, 'E'},
341 {"file", required_argument, NULL, 'f'},
342 {"field-separator", required_argument, NULL, 'F'},
343 {"host", required_argument, NULL, 'h'},
344 {"html", no_argument, NULL, 'H'},
345 {"list", no_argument, NULL, 'l'},
346 {"no-readline", no_argument, NULL, 'n'},
347 {"output", required_argument, NULL, 'o'},
348 {"port", required_argument, NULL, 'p'},
349 {"pset", required_argument, NULL, 'P'},
350 {"quiet", no_argument, NULL, 'q'},
351 {"record-separator", required_argument, NULL, 'R'},
352 {"single-step", no_argument, NULL, 's'},
353 {"single-line", no_argument, NULL, 'S'},
354 {"tuples-only", no_argument, NULL, 't'},
355 {"table-attr", required_argument, NULL, 'T'},
356 {"username", required_argument, NULL, 'U'},
357 {"set", required_argument, NULL, 'v'},
358 {"variable", required_argument, NULL, 'v'},
359 {"version", no_argument, NULL, 'V'},
360 {"password", no_argument, NULL, 'W'},
361 {"expanded", no_argument, NULL, 'x'},
362 {"no-psqlrc", no_argument, NULL, 'X'},
363 {"help", no_argument, NULL, '?'},
371 bool used_old_u_option = false;
373 memset(options, 0, sizeof *options);
375 while ((c = getopt_long(argc, argv, "aAc:d:eEf:F:h:Hlno:p:P:qR:sStT:uU:v:VWxX?",
376 long_options, &optindex)) != -1)
381 SetVariable(pset.vars, "ECHO", "all");
384 pset.popt.topt.format = PRINT_UNALIGNED;
387 options->action_string = optarg;
388 if (optarg[0] == '\\')
390 options->action = ACT_SINGLE_SLASH;
391 options->action_string++;
394 options->action = ACT_SINGLE_QUERY;
397 options->dbname = optarg;
400 SetVariable(pset.vars, "ECHO", "queries");
403 SetVariableBool(pset.vars, "ECHO_HIDDEN");
406 options->action = ACT_FILE;
407 options->action_string = optarg;
410 pset.popt.topt.fieldSep = pg_strdup(optarg);
413 options->host = optarg;
416 pset.popt.topt.format = PRINT_HTML;
419 options->action = ACT_LIST_DB;
422 options->no_readline = true;
428 options->port = optarg;
436 value = pg_strdup(optarg);
437 equal_loc = strchr(value, '=');
439 result = do_pset(value, NULL, &pset.popt, true);
443 result = do_pset(value, equal_loc + 1, &pset.popt, true);
448 fprintf(stderr, gettext("%s: couldn't set printing parameter \"%s\"\n"), pset.progname, value);
456 SetVariableBool(pset.vars, "QUIET");
459 pset.popt.topt.recordSep = pg_strdup(optarg);
462 SetVariableBool(pset.vars, "SINGLESTEP");
465 SetVariableBool(pset.vars, "SINGLELINE");
468 pset.popt.topt.tuples_only = true;
471 pset.popt.topt.tableAttr = pg_strdup(optarg);
474 pset.getPassword = true;
475 options->username = "\001"; /* hopefully nobody has
477 /* this option is out */
478 used_old_u_option = true;
481 options->username = optarg;
488 value = pg_strdup(optarg);
489 equal_loc = strchr(value, '=');
492 if (!DeleteVariable(pset.vars, value))
494 fprintf(stderr, gettext("%s: could not delete variable \"%s\"\n"),
495 pset.progname, value);
502 if (!SetVariable(pset.vars, value, equal_loc + 1))
504 fprintf(stderr, gettext("%s: could not set variable \"%s\"\n"),
505 pset.progname, value);
517 pset.getPassword = true;
520 pset.popt.topt.expanded = true;
523 options->no_psqlrc = true;
526 /* Actual help option given */
527 if (strcmp(argv[optind - 1], "-?") == 0 || strcmp(argv[optind - 1], "--help") == 0)
532 /* unknown option reported by getopt */
535 fprintf(stderr, gettext("Try \"%s --help\" for more information.\n"),
541 fprintf(stderr, gettext("Try \"%s --help\" for more information.\n"),
549 * if we still have arguments, use it as the database name and
552 while (argc - optind >= 1)
554 if (!options->dbname)
555 options->dbname = argv[optind];
556 else if (!options->username)
557 options->username = argv[optind];
559 fprintf(stderr, gettext("%s: warning: extra command-line argument \"%s\" ignored\n"),
560 pset.progname, argv[optind]);
565 if (used_old_u_option && !QUIET())
566 fprintf(stderr, gettext("%s: Warning: The -u option is deprecated. Use -U.\n"), pset.progname);
571 #error "You must compile this file with SYSCONFDIR defined."
576 * Load .psqlrc file, if found.
581 char *globalFile = SYSCONFDIR "/" SYSPSQLRC;
585 process_psqlrc_file(globalFile);
587 if ((home = getenv("HOME")) != NULL)
589 psqlrc = pg_malloc(strlen(home) + 1 + strlen(PSQLRC) + 1);
590 sprintf(psqlrc, "%s/%s", home, PSQLRC);
591 process_psqlrc_file(psqlrc);
598 process_psqlrc_file(char *filename)
602 #if defined(WIN32) && (!defined(__MINGW32__))
606 psqlrc = pg_malloc(strlen(filename) + 1 + strlen(PG_VERSION) + 1);
607 sprintf(psqlrc, "%s-%s", filename, PG_VERSION);
609 if (access(psqlrc, R_OK) == 0)
610 process_file(psqlrc);
611 else if (access(filename, R_OK) == 0)
612 process_file(filename);
620 * This output format is intended to match GNU standards.
625 puts("psql (PostgreSQL) " PG_VERSION);
627 #if defined(USE_READLINE)
628 puts(gettext("contains support for command-line editing"));
637 * Prints information about the current SSL connection, if SSL is in use
646 ssl = PQgetssl(pset.db);
650 SSL_get_cipher_bits(ssl, &sslbits);
651 printf(gettext("SSL connection (cipher: %s, bits: %i)\n\n"),
652 SSL_get_cipher(ssl), sslbits);
662 * Prints a warning when win32 console codepage differs from Windows codepage
666 checkWin32Codepage(void)
668 unsigned int wincp, concp;
671 concp = GetConsoleCP();
672 if (wincp != concp) {
673 printf("Warning: Console codepage (%u) differs from windows codepage (%u)\n"
674 " 8-bit characters will not work correctly. See PostgreSQL\n"
675 " documentation \"Installation on Windows\" for details.\n\n",