📄 startup.c
字号:
/* * psql - the PostgreSQL interactive terminal * * Copyright (c) 2000-2005, PostgreSQL Global Development Group * * $PostgreSQL: pgsql/src/bin/psql/startup.c,v 1.126.2.2 2005/11/22 18:23:27 momjian Exp $ */#include "postgres_fe.h"#include <sys/types.h>#ifndef WIN32#include <unistd.h>#else /* WIN32 */#include <io.h>#include <win32.h>#endif /* WIN32 */#include "getopt_long.h"#ifndef HAVE_INT_OPTRESETint optreset;#endif#include <locale.h>#include "libpq-fe.h"#include "command.h"#include "common.h"#include "describe.h"#include "help.h"#include "input.h"#include "mainloop.h"#include "print.h"#include "settings.h"#include "variables.h"#include "mb/pg_wchar.h"/* * Global psql options */PsqlSettings pset;#ifndef WIN32#define SYSPSQLRC "psqlrc"#define PSQLRC ".psqlrc"#else#define SYSPSQLRC "psqlrc"#define PSQLRC "psqlrc.conf"#endif/* * Structures to pass information between the option parsing routine * and the main function */enum _actions{ ACT_NOTHING = 0, ACT_SINGLE_SLASH, ACT_LIST_DB, ACT_SINGLE_QUERY, ACT_FILE};struct adhoc_opts{ char *dbname; char *host; char *port; char *username; char *logfilename; enum _actions action; char *action_string; bool no_readline; bool no_psqlrc;};static int parse_version(const char *versionString);static void parse_psql_options(int argc, char *argv[], struct adhoc_opts * options);static void process_psqlrc(char *argv0);static void process_psqlrc_file(char *filename);static void showVersion(void);#ifdef USE_SSLstatic void printSSLInfo(void);#endif#ifdef WIN32static void checkWin32Codepage(void);#endif/* * * main * */intmain(int argc, char *argv[]){ struct adhoc_opts options; int successResult; char *username = NULL; char *password = NULL; char *password_prompt = NULL; bool need_pass; set_pglocale_pgservice(argv[0], "psql"); if (argc > 1) { if (strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-?") == 0) { usage(); exit(EXIT_SUCCESS); } if (strcmp(argv[1], "--version") == 0 || strcmp(argv[1], "-V") == 0) { showVersion(); exit(EXIT_SUCCESS); } } pset.progname = get_progname(argv[0]);#ifdef WIN32 setvbuf(stderr, NULL, _IONBF, 0); setup_win32_locks();#endif setDecimalLocale(); pset.cur_cmd_source = stdin; pset.cur_cmd_interactive = false; pset.encoding = PQenv2encoding(); pset.vars = CreateVariableSpace(); if (!pset.vars) { fprintf(stderr, _("%s: out of memory\n"), pset.progname); exit(EXIT_FAILURE); } pset.popt.topt.format = PRINT_ALIGNED; pset.queryFout = stdout; pset.popt.topt.border = 1; pset.popt.topt.pager = 1; pset.popt.default_footer = true; SetVariable(pset.vars, "VERSION", PG_VERSION_STR); /* Default values for variables */ SetVariableBool(pset.vars, "AUTOCOMMIT"); SetVariable(pset.vars, "VERBOSITY", "default"); SetVariable(pset.vars, "PROMPT1", DEFAULT_PROMPT1); SetVariable(pset.vars, "PROMPT2", DEFAULT_PROMPT2); SetVariable(pset.vars, "PROMPT3", DEFAULT_PROMPT3); pset.verbosity = PQERRORS_DEFAULT; pset.notty = (!isatty(fileno(stdin)) || !isatty(fileno(stdout))); /* This is obsolete and should be removed sometime. */#ifdef PSQL_ALWAYS_GET_PASSWORDS pset.getPassword = true;#else pset.getPassword = false;#endif parse_psql_options(argc, argv, &options); if (!pset.popt.topt.fieldSep) pset.popt.topt.fieldSep = pg_strdup(DEFAULT_FIELD_SEP); if (!pset.popt.topt.recordSep) pset.popt.topt.recordSep = pg_strdup(DEFAULT_RECORD_SEP); if (options.username) { /* * The \001 is a hack to support the deprecated -u option which issues * a username prompt. The recommended option is -U followed by the * name on the command line. */ if (strcmp(options.username, "\001") == 0) username = simple_prompt("User name: ", 100, true); else username = pg_strdup(options.username); } if (options.username == NULL) password_prompt = pg_strdup(_("Password: ")); else { password_prompt = malloc(strlen(_("Password for user %s: ")) - 2 + strlen(options.username) + 1); sprintf(password_prompt, _("Password for user %s: "), options.username); } if (pset.getPassword) password = simple_prompt(password_prompt, 100, false); /* loop until we have a password if requested by backend */ do { need_pass = false; pset.db = PQsetdbLogin(options.host, options.port, NULL, NULL, options.action == ACT_LIST_DB && options.dbname == NULL ? "postgres" : options.dbname, username, password); if (PQstatus(pset.db) == CONNECTION_BAD && strcmp(PQerrorMessage(pset.db), PQnoPasswordSupplied) == 0 && !feof(stdin)) { PQfinish(pset.db); need_pass = true; free(password); password = NULL; password = simple_prompt(password_prompt, 100, false); } } while (need_pass); free(username); free(password); free(password_prompt); if (PQstatus(pset.db) == CONNECTION_BAD) { fprintf(stderr, "%s: %s", pset.progname, PQerrorMessage(pset.db)); PQfinish(pset.db); exit(EXIT_BADCONN); } PQsetNoticeProcessor(pset.db, NoticeProcessor, NULL); SyncVariables(); /* Grab the backend server version */ pset.sversion = PQserverVersion(pset.db); if (options.action == ACT_LIST_DB) { int success = listAllDbs(false); PQfinish(pset.db); exit(success ? EXIT_SUCCESS : EXIT_FAILURE); } if (options.logfilename) { pset.logfile = fopen(options.logfilename, "a"); if (!pset.logfile) fprintf(stderr, _("%s: could not open log file \"%s\": %s\n"), pset.progname, options.logfilename, strerror(errno)); } /* * Now find something to do */ /* * process file given by -f */ if (options.action == ACT_FILE && strcmp(options.action_string, "-") != 0) { if (!options.no_psqlrc) process_psqlrc(argv[0]); successResult = process_file(options.action_string); } /* * process slash command if one was given to -c */ else if (options.action == ACT_SINGLE_SLASH) { PsqlScanState scan_state; if (VariableEquals(pset.vars, "ECHO", "all")) puts(options.action_string); scan_state = psql_scan_create(); psql_scan_setup(scan_state, options.action_string, strlen(options.action_string)); successResult = HandleSlashCmds(scan_state, NULL) != CMD_ERROR ? EXIT_SUCCESS : EXIT_FAILURE; psql_scan_destroy(scan_state); } /* * If the query given to -c was a normal one, send it */ else if (options.action == ACT_SINGLE_QUERY) { if (VariableEquals(pset.vars, "ECHO", "all")) puts(options.action_string); successResult = SendQuery(options.action_string) ? EXIT_SUCCESS : EXIT_FAILURE; } /* * or otherwise enter interactive main loop */ else { if (!options.no_psqlrc) process_psqlrc(argv[0]); if (!QUIET() && !pset.notty) { int client_ver = parse_version(PG_VERSION); if (pset.sversion != client_ver) { const char *server_version; char server_ver_str[16]; /* Try to get full text form, might include "devel" etc */ server_version = PQparameterStatus(pset.db, "server_version"); if (!server_version) { snprintf(server_ver_str, sizeof(server_ver_str), "%d.%d.%d", pset.sversion / 10000, (pset.sversion / 100) % 100, pset.sversion % 100); server_version = server_ver_str; } printf(_("Welcome to %s %s (server %s), the PostgreSQL interactive terminal.\n\n"), pset.progname, PG_VERSION, server_version); } else printf(_("Welcome to %s %s, the PostgreSQL interactive terminal.\n\n"), pset.progname, PG_VERSION); printf(_("Type: \\copyright for distribution terms\n" " \\h for help with SQL commands\n" " \\? for help with psql commands\n" " \\g or terminate with semicolon to execute query\n" " \\q to quit\n\n")); if (pset.sversion / 100 != client_ver / 100) printf(_("WARNING: You are connected to a server with major version %d.%d,\n" "but your %s client is major version %d.%d. Some backslash commands,\n" "such as \\d, might not work properly.\n\n"), pset.sversion / 10000, (pset.sversion / 100) % 100, pset.progname, client_ver / 10000, (client_ver / 100) % 100);#ifdef USE_SSL printSSLInfo();#endif#ifdef WIN32 checkWin32Codepage();#endif } if (!pset.notty) initializeInput(options.no_readline ? 0 : 1); if (options.action_string) /* -f - was used */ pset.inputfile = "<stdin>"; successResult = MainLoop(stdin); } /* clean up */ if (pset.logfile) fclose(pset.logfile); PQfinish(pset.db); setQFout(NULL); return successResult;}/*
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -