Esempio n. 1
0
static void
parse_psql_options(int argc, char *argv[], struct adhoc_opts * options)
{
    static struct option long_options[] =
    {
        {"echo-all", no_argument, NULL, 'a'},
        {"no-align", no_argument, NULL, 'A'},
        {"command", required_argument, NULL, 'c'},
        {"dbname", required_argument, NULL, 'd'},
        {"echo-queries", no_argument, NULL, 'e'},
        {"echo-errors", no_argument, NULL, 'b'},
        {"echo-hidden", no_argument, NULL, 'E'},
        {"file", required_argument, NULL, 'f'},
        {"field-separator", required_argument, NULL, 'F'},
        {"field-separator-zero", no_argument, NULL, 'z'},
        {"host", required_argument, NULL, 'h'},
        {"html", no_argument, NULL, 'H'},
        {"list", no_argument, NULL, 'l'},
        {"log-file", required_argument, NULL, 'L'},
        {"no-readline", no_argument, NULL, 'n'},
        {"single-transaction", no_argument, NULL, '1'},
        {"output", required_argument, NULL, 'o'},
        {"port", required_argument, NULL, 'p'},
        {"pset", required_argument, NULL, 'P'},
        {"quiet", no_argument, NULL, 'q'},
        {"record-separator", required_argument, NULL, 'R'},
        {"record-separator-zero", no_argument, NULL, '0'},
        {"single-step", no_argument, NULL, 's'},
        {"single-line", no_argument, NULL, 'S'},
        {"tuples-only", no_argument, NULL, 't'},
        {"table-attr", required_argument, NULL, 'T'},
        {"username", required_argument, NULL, 'U'},
        {"set", required_argument, NULL, 'v'},
        {"variable", required_argument, NULL, 'v'},
        {"version", no_argument, NULL, 'V'},
        {"no-password", no_argument, NULL, 'w'},
        {"password", no_argument, NULL, 'W'},
        {"expanded", no_argument, NULL, 'x'},
        {"no-psqlrc", no_argument, NULL, 'X'},
        {"help", optional_argument, NULL, 1},
        {NULL, 0, NULL, 0}
    };

    int			optindex;
    int			c;

    memset(options, 0, sizeof *options);

    while ((c = getopt_long(argc, argv, "aAbc:d:eEf:F:h:HlL:no:p:P:qR:sStT:U:v:VwWxXz?01",
                            long_options, &optindex)) != -1)
    {
        switch (c)
        {
        case 'a':
            SetVariable(pset.vars, "ECHO", "all");
            break;
        case 'A':
            pset.popt.topt.format = PRINT_UNALIGNED;
            break;
        case 'b':
            SetVariable(pset.vars, "ECHO", "errors");
            break;
        case 'c':
            options->action_string = pg_strdup(optarg);
            if (optarg[0] == '\\')
            {
                options->action = ACT_SINGLE_SLASH;
                options->action_string++;
            }
            else
                options->action = ACT_SINGLE_QUERY;
            break;
        case 'd':
            options->dbname = pg_strdup(optarg);
            break;
        case 'e':
            SetVariable(pset.vars, "ECHO", "queries");
            break;
        case 'E':
            SetVariableBool(pset.vars, "ECHO_HIDDEN");
            break;
        case 'f':
            options->action = ACT_FILE;
            options->action_string = pg_strdup(optarg);
            break;
        case 'F':
            pset.popt.topt.fieldSep.separator = pg_strdup(optarg);
            pset.popt.topt.fieldSep.separator_zero = false;
            break;
        case 'h':
            options->host = pg_strdup(optarg);
            break;
        case 'H':
            pset.popt.topt.format = PRINT_HTML;
            break;
        case 'l':
            options->action = ACT_LIST_DB;
            break;
        case 'L':
            options->logfilename = pg_strdup(optarg);
            break;
        case 'n':
            options->no_readline = true;
            break;
        case 'o':
            if (!setQFout(optarg))
                exit(EXIT_FAILURE);
            break;
        case 'p':
            options->port = pg_strdup(optarg);
            break;
        case 'P':
        {
            char	   *value;
            char	   *equal_loc;
            bool		result;

            value = pg_strdup(optarg);
            equal_loc = strchr(value, '=');
            if (!equal_loc)
                result = do_pset(value, NULL, &pset.popt, true);
            else
            {
                *equal_loc = '\0';
                result = do_pset(value, equal_loc + 1, &pset.popt, true);
            }

            if (!result)
            {
                fprintf(stderr, _("%s: could not set printing parameter \"%s\"\n"), pset.progname, value);
                exit(EXIT_FAILURE);
            }

            free(value);
            break;
        }
        case 'q':
            SetVariableBool(pset.vars, "QUIET");
            break;
        case 'R':
            pset.popt.topt.recordSep.separator = pg_strdup(optarg);
            pset.popt.topt.recordSep.separator_zero = false;
            break;
        case 's':
            SetVariableBool(pset.vars, "SINGLESTEP");
            break;
        case 'S':
            SetVariableBool(pset.vars, "SINGLELINE");
            break;
        case 't':
            pset.popt.topt.tuples_only = true;
            break;
        case 'T':
            pset.popt.topt.tableAttr = pg_strdup(optarg);
            break;
        case 'U':
            options->username = pg_strdup(optarg);
            break;
        case 'v':
        {
            char	   *value;
            char	   *equal_loc;

            value = pg_strdup(optarg);
            equal_loc = strchr(value, '=');
            if (!equal_loc)
            {
                if (!DeleteVariable(pset.vars, value))
                {
                    fprintf(stderr, _("%s: could not delete variable \"%s\"\n"),
                            pset.progname, value);
                    exit(EXIT_FAILURE);
                }
            }
            else
            {
                *equal_loc = '\0';
                if (!SetVariable(pset.vars, value, equal_loc + 1))
                {
                    fprintf(stderr, _("%s: could not set variable \"%s\"\n"),
                            pset.progname, value);
                    exit(EXIT_FAILURE);
                }
            }

            free(value);
            break;
        }
        case 'V':
            showVersion();
            exit(EXIT_SUCCESS);
        case 'w':
            pset.getPassword = TRI_NO;
            break;
        case 'W':
            pset.getPassword = TRI_YES;
            break;
        case 'x':
            pset.popt.topt.expanded = true;
            break;
        case 'X':
            options->no_psqlrc = true;
            break;
        case 'z':
            pset.popt.topt.fieldSep.separator_zero = true;
            break;
        case '0':
            pset.popt.topt.recordSep.separator_zero = true;
            break;
        case '1':
            options->single_txn = true;
            break;
        case '?':
            /* Actual help option given */
            if (strcmp(argv[optind - 1], "-?") == 0)
            {
                usage(NOPAGER);
                exit(EXIT_SUCCESS);
            }
            /* unknown option reported by getopt */
            else
                goto unknown_option;
            break;
        case 1:
        {
            if (!optarg || strcmp(optarg, "options") == 0)
                usage(NOPAGER);
            else if (optarg && strcmp(optarg, "commands") == 0)
                slashUsage(NOPAGER);
            else if (optarg && strcmp(optarg, "variables") == 0)
                helpVariables(NOPAGER);
            else
                goto unknown_option;

            exit(EXIT_SUCCESS);
        }
        break;
        default:
unknown_option:
            fprintf(stderr, _("Try \"%s --help\" for more information.\n"),
                    pset.progname);
            exit(EXIT_FAILURE);
            break;
        }
    }

    /*
     * if we still have arguments, use it as the database name and username
     */
    while (argc - optind >= 1)
    {
        if (!options->dbname)
            options->dbname = argv[optind];
        else if (!options->username)
            options->username = argv[optind];
        else if (!pset.quiet)
            fprintf(stderr, _("%s: warning: extra command-line argument \"%s\" ignored\n"),
                    pset.progname, argv[optind]);

        optind++;
    }
}
Esempio n. 2
0
/*
 *
 * main
 *
 */
int
main(int argc, char *argv[])
{
    struct adhoc_opts options;
    int			successResult;
    char	   *password = NULL;
    char	   *password_prompt = NULL;
    bool		new_pass;

    set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("psql"));

    if (argc > 1)
    {
        if ((strcmp(argv[1], "-?") == 0) || (argc == 2 && (strcmp(argv[1], "--help") == 0)))
        {
            usage(NOPAGER);
            exit(EXIT_SUCCESS);
        }
        if (strcmp(argv[1], "--version") == 0 || strcmp(argv[1], "-V") == 0)
        {
            showVersion();
            exit(EXIT_SUCCESS);
        }
    }

#ifdef WIN32
    setvbuf(stderr, NULL, _IONBF, 0);
#endif

    pset.progname = get_progname(argv[0]);

    pset.db = NULL;
    setDecimalLocale();
    pset.encoding = PQenv2encoding();
    pset.queryFout = stdout;
    pset.queryFoutPipe = false;
    pset.copyStream = NULL;
    pset.cur_cmd_source = stdin;
    pset.cur_cmd_interactive = false;

    /* We rely on unmentioned fields of pset.popt to start out 0/false/NULL */
    pset.popt.topt.format = PRINT_ALIGNED;
    pset.popt.topt.border = 1;
    pset.popt.topt.pager = 1;
    pset.popt.topt.pager_min_lines = 0;
    pset.popt.topt.start_table = true;
    pset.popt.topt.stop_table = true;
    pset.popt.topt.default_footer = true;

    pset.popt.topt.unicode_border_linestyle = UNICODE_LINESTYLE_SINGLE;
    pset.popt.topt.unicode_column_linestyle = UNICODE_LINESTYLE_SINGLE;
    pset.popt.topt.unicode_header_linestyle = UNICODE_LINESTYLE_SINGLE;

    refresh_utf8format(&(pset.popt.topt));

    /* We must get COLUMNS here before readline() sets it */
    pset.popt.topt.env_columns = getenv("COLUMNS") ? atoi(getenv("COLUMNS")) : 0;

    pset.notty = (!isatty(fileno(stdin)) || !isatty(fileno(stdout)));

    pset.getPassword = TRI_DEFAULT;

    EstablishVariableSpace();

    SetVariable(pset.vars, "VERSION", PG_VERSION_STR);

    /* Default values for variables */
    SetVariableBool(pset.vars, "AUTOCOMMIT");
    SetVariable(pset.vars, "VERBOSITY", "default");
    SetVariable(pset.vars, "SHOW_CONTEXT", "errors");
    SetVariable(pset.vars, "PROMPT1", DEFAULT_PROMPT1);
    SetVariable(pset.vars, "PROMPT2", DEFAULT_PROMPT2);
    SetVariable(pset.vars, "PROMPT3", DEFAULT_PROMPT3);

    parse_psql_options(argc, argv, &options);

    /*
     * If no action was specified and we're in non-interactive mode, treat it
     * as if the user had specified "-f -".  This lets single-transaction mode
     * work in this case.
     */
    if (options.action == ACT_NOTHING && pset.notty)
    {
        options.action = ACT_FILE;
        options.action_string = NULL;
    }

    /* Bail out if -1 was specified but will be ignored. */
    if (options.single_txn && options.action != ACT_FILE && options.action == ACT_NOTHING)
    {
        fprintf(stderr, _("%s: -1 can only be used in non-interactive mode\n"), pset.progname);
        exit(EXIT_FAILURE);
    }

    if (!pset.popt.topt.fieldSep.separator &&
            !pset.popt.topt.fieldSep.separator_zero)
    {
        pset.popt.topt.fieldSep.separator = pg_strdup(DEFAULT_FIELD_SEP);
        pset.popt.topt.fieldSep.separator_zero = false;
    }
    if (!pset.popt.topt.recordSep.separator &&
            !pset.popt.topt.recordSep.separator_zero)
    {
        pset.popt.topt.recordSep.separator = pg_strdup(DEFAULT_RECORD_SEP);
        pset.popt.topt.recordSep.separator_zero = false;
    }

    if (options.username == NULL)
        password_prompt = pg_strdup(_("Password: "******"Password for user %s: "),
                                   options.username);

    if (pset.getPassword == TRI_YES)
        password = simple_prompt(password_prompt, 100, false);

    /* loop until we have a password if requested by backend */
    do
    {
#define PARAMS_ARRAY_SIZE	8
        const char **keywords = pg_malloc(PARAMS_ARRAY_SIZE * sizeof(*keywords));
        const char **values = pg_malloc(PARAMS_ARRAY_SIZE * sizeof(*values));

        keywords[0] = "host";
        values[0] = options.host;
        keywords[1] = "port";
        values[1] = options.port;
        keywords[2] = "user";
        values[2] = options.username;
        keywords[3] = "password";
        values[3] = password;
        keywords[4] = "dbname";
        values[4] = (options.action == ACT_LIST_DB &&
                     options.dbname == NULL) ?
                    "postgres" : options.dbname;
        keywords[5] = "fallback_application_name";
        values[5] = pset.progname;
        keywords[6] = "client_encoding";
        values[6] = (pset.notty || getenv("PGCLIENTENCODING")) ? NULL : "auto";
        keywords[7] = NULL;
        values[7] = NULL;

        new_pass = false;
        pset.db = PQconnectdbParams(keywords, values, true);
        free(keywords);
        free(values);

        if (PQstatus(pset.db) == CONNECTION_BAD &&
                PQconnectionNeedsPassword(pset.db) &&
                password == NULL &&
                pset.getPassword != TRI_NO)
        {
            PQfinish(pset.db);
            password = simple_prompt(password_prompt, 100, false);
            new_pass = true;
        }
    } while (new_pass);

    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);
    }

    setup_cancel_handler();

    PQsetNoticeProcessor(pset.db, NoticeProcessor, NULL);

    SyncVariables();

    if (options.action == ACT_LIST_DB)
    {
        int			success;

        if (!options.no_psqlrc)
            process_psqlrc(argv[0]);

        success = listAllDbs(NULL, 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)
    {
        if (!options.no_psqlrc)
            process_psqlrc(argv[0]);

        successResult = process_file(options.action_string, options.single_txn, false);
    }

    /*
     * process slash command if one was given to -c
     */
    else if (options.action == ACT_SINGLE_SLASH)
    {
        PsqlScanState scan_state;

        if (pset.echo == PSQL_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) != PSQL_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 (pset.echo == PSQL_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]);

        connection_warnings(true);
        if (!pset.quiet)
            printf(_("Type \"help\" for help.\n\n"));
        initializeInput(options.no_readline ? 0 : 1);
        successResult = MainLoop(stdin);
    }

    /* clean up */
    if (pset.logfile)
        fclose(pset.logfile);
    PQfinish(pset.db);
    setQFout(NULL);

    return successResult;
}
Esempio n. 3
0
/*
 *
 * main
 *
 */
int
main(int argc, char *argv[])
{
	struct adhoc_opts options;
	int			successResult;
	char	   *password = NULL;
	char	   *password_prompt = NULL;
	bool		new_pass;

	set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("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);
		}
	}

#ifdef WIN32
	setvbuf(stderr, NULL, _IONBF, 0);
#endif

	setup_cancel_handler();

	pset.progname = get_progname(argv[0]);

	pset.db = NULL;
	setDecimalLocale();
	pset.encoding = PQenv2encoding();
	pset.queryFout = stdout;
	pset.queryFoutPipe = false;
	pset.cur_cmd_source = stdin;
	pset.cur_cmd_interactive = false;

	/* We rely on unmentioned fields of pset.popt to start out 0/false/NULL */
	pset.popt.topt.format = PRINT_ALIGNED;
	pset.popt.topt.border = 1;
	pset.popt.topt.pager = 1;
	pset.popt.topt.start_table = true;
	pset.popt.topt.stop_table = true;
	pset.popt.default_footer = true;
	/* We must get COLUMNS here before readline() sets it */
	pset.popt.topt.env_columns = getenv("COLUMNS") ? atoi(getenv("COLUMNS")) : 0;

	pset.notty = (!isatty(fileno(stdin)) || !isatty(fileno(stdout)));

	pset.getPassword = TRI_DEFAULT;

	EstablishVariableSpace();

	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);

	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 == NULL)
		password_prompt = pg_strdup(_("Password: "******"Password for user %s: ")) - 2 +
								 strlen(options.username) + 1);
		sprintf(password_prompt, _("Password for user %s: "),
				options.username);
	}

	if (pset.getPassword == TRI_YES)
		password = simple_prompt(password_prompt, 100, false);

	/* loop until we have a password if requested by backend */
	do
	{
		new_pass = false;
		pset.db = PQsetdbLogin(options.host, options.port, NULL, NULL,
					options.action == ACT_LIST_DB && options.dbname == NULL ?
							   "postgres" : options.dbname,
							   options.username, password);

		if (PQstatus(pset.db) == CONNECTION_BAD &&
			PQconnectionNeedsPassword(pset.db) &&
			password == NULL &&
			pset.getPassword != TRI_NO)
		{
			PQfinish(pset.db);
			password = simple_prompt(password_prompt, 100, false);
			new_pass = true;
		}
	} while (new_pass);

	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();

	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, options.single_txn);
	}

	/*
	 * process slash command if one was given to -c
	 */
	else if (options.action == ACT_SINGLE_SLASH)
	{
		PsqlScanState scan_state;

		if (pset.echo == PSQL_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) != PSQL_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 (pset.echo == PSQL_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]);

		connection_warnings();
		if (!pset.quiet && !pset.notty)
			printf(_("Type \"help\" for help.\n\n"));
		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;
}