diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c index a3ed96689d..75092fc4a4 100644 --- a/src/backend/tcop/postgres.c +++ b/src/backend/tcop/postgres.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/tcop/postgres.c,v 1.571 2009/08/29 19:26:51 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/tcop/postgres.c,v 1.572 2009/09/01 00:09:42 tgl Exp $ * * NOTES * this is the "main" module of the postgres backend and @@ -2862,7 +2862,7 @@ get_stats_option_name(const char *arg) * from the client's startup packet. The latter have the same syntax but * may be restricted in what they can do. * - * argv[0] is the program name either way. + * argv[0] is ignored in either case (it's assumed to be the program name). * * ctx is PGC_POSTMASTER for secure options, PGC_BACKEND for insecure options * coming from the client, or PGC_SUSET for insecure options coming from @@ -2871,11 +2871,10 @@ get_stats_option_name(const char *arg) * Returns the database name extracted from the command line, if any. * ---------------------------------------------------------------- */ -static const char * +const char * process_postgres_switches(int argc, char *argv[], GucContext ctx) { const char *dbname; - const char *argv0 = argv[0]; bool secure = (ctx == PGC_POSTMASTER); int errs = 0; GucSource gucsource; @@ -3073,13 +3072,13 @@ process_postgres_switches(int argc, char *argv[], GucContext ctx) ereport(FATAL, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("invalid command-line arguments for server process"), - errhint("Try \"%s --help\" for more information.", argv0))); + errhint("Try \"%s --help\" for more information.", progname))); else ereport(FATAL, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("%s: invalid command-line arguments", - argv0), - errhint("Try \"%s --help\" for more information.", argv0))); + progname), + errhint("Try \"%s --help\" for more information.", progname))); } if (argc - optind == 1) @@ -3114,8 +3113,6 @@ int PostgresMain(int argc, char *argv[], const char *username) { const char *dbname; - bool am_superuser; - GucContext ctx; int firstchar; char stack_base; StringInfoData input_message; @@ -3176,13 +3173,13 @@ PostgresMain(int argc, char *argv[], const char *username) ereport(FATAL, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("%s: no database nor user name specified", - argv[0]))); + progname))); } /* Acquire configuration parameters, unless inherited from postmaster */ if (!IsUnderPostmaster) { - if (!SelectConfigFiles(userDoption, argv[0])) + if (!SelectConfigFiles(userDoption, progname)) proc_exit(1); /* If timezone is not set, determine what the OS uses */ pg_timezone_initialize(); @@ -3314,7 +3311,7 @@ PostgresMain(int argc, char *argv[], const char *username) * it inside InitPostgres() instead. In particular, anything that * involves database access should be there, not here. */ - am_superuser = InitPostgres(dbname, InvalidOid, username, NULL); + InitPostgres(dbname, InvalidOid, username, NULL); /* * If the PostmasterContext is still around, recycle the space; we don't @@ -3331,70 +3328,6 @@ PostgresMain(int argc, char *argv[], const char *username) SetProcessingMode(NormalProcessing); - set_ps_display("startup", false); - - /* - * Now that we know if client is a superuser, we can try to apply any - * command-line options passed in the startup packet. - */ - ctx = am_superuser ? PGC_SUSET : PGC_BACKEND; - - if (MyProcPort != NULL && - MyProcPort->cmdline_options != NULL) - { - /* - * The maximum possible number of commandline arguments that could - * come from MyProcPort->cmdline_options is (strlen + 1) / 2; see - * pg_split_opts(). - */ - char **av; - int maxac; - int ac; - - maxac = 2 + (strlen(MyProcPort->cmdline_options) + 1) / 2; - - av = (char **) palloc(maxac * sizeof(char *)); - ac = 0; - - av[ac++] = argv[0]; - - /* Note this mangles MyProcPort->cmdline_options */ - pg_split_opts(av, &ac, MyProcPort->cmdline_options); - - av[ac] = NULL; - - Assert(ac < maxac); - - (void) process_postgres_switches(ac, av, ctx); - } - - /* - * Process any additional GUC variable settings passed in startup packet. - * These are handled exactly like command-line variables. - */ - if (MyProcPort != NULL) - { - ListCell *gucopts = list_head(MyProcPort->guc_options); - - while (gucopts) - { - char *name; - char *value; - - name = lfirst(gucopts); - gucopts = lnext(gucopts); - - value = lfirst(gucopts); - gucopts = lnext(gucopts); - - SetConfigOption(name, value, ctx, PGC_S_CLIENT); - } - } - - /* Apply PostAuthDelay as soon as we've read all options */ - if (PostAuthDelay > 0) - pg_usleep(PostAuthDelay * 1000000L); - /* * Now all GUC states are fully set up. Report them to client if * appropriate. diff --git a/src/backend/utils/init/postinit.c b/src/backend/utils/init/postinit.c index 2d7253312f..5321afc1b8 100644 --- a/src/backend/utils/init/postinit.c +++ b/src/backend/utils/init/postinit.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/utils/init/postinit.c,v 1.196 2009/08/31 19:41:00 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/utils/init/postinit.c,v 1.197 2009/09/01 00:09:42 tgl Exp $ * * *------------------------------------------------------------------------- @@ -44,11 +44,13 @@ #include "storage/procsignal.h" #include "storage/sinvaladt.h" #include "storage/smgr.h" +#include "tcop/tcopprot.h" #include "utils/acl.h" #include "utils/fmgroids.h" #include "utils/guc.h" #include "utils/pg_locale.h" #include "utils/portal.h" +#include "utils/ps_status.h" #include "utils/snapmgr.h" #include "utils/syscache.h" #include "utils/tqual.h" @@ -217,6 +219,8 @@ PerformAuthentication(Port *port) (errmsg("connection authorized: user=%s database=%s", port->user_name, port->database_name))); + set_ps_display("startup", false); + ClientAuthInProgress = false; /* client_min_messages is active now */ } @@ -256,7 +260,7 @@ CheckMyDatabase(const char *name, bool am_superuser) * a way to recover from disabling all access to all databases, for * example "UPDATE pg_database SET datallowconn = false;". * - * We do not enforce them for the autovacuum worker processes either. + * We do not enforce them for autovacuum worker processes either. */ if (IsUnderPostmaster && !IsAutoVacuumWorkerProcess()) { @@ -464,10 +468,6 @@ BaseInit(void) * doesn't use any parameters either, because it only goes far enough to be * able to read pg_database; it doesn't connect to any particular database. * - * The return value indicates whether the userID is a superuser. (That - * can only be tested inside a transaction, so we want to do it during - * the startup transaction rather than doing a separate one in postgres.c.) - * * As of PostgreSQL 8.2, we expect InitProcess() was already called, so we * already have a PGPROC struct ... but it's not completely filled in yet. * @@ -475,13 +475,13 @@ BaseInit(void) * Be very careful with the order of calls in the InitPostgres function. * -------------------------------- */ -bool +void InitPostgres(const char *in_dbname, Oid dboid, const char *username, char *out_dbname) { bool bootstrap = IsBootstrapProcessingMode(); - bool autovacuum = IsAutoVacuumWorkerProcess(); bool am_superuser; + GucContext gucctx; char *fullpath; char dbname[NAMEDATALEN]; @@ -558,7 +558,7 @@ InitPostgres(const char *in_dbname, Oid dboid, const char *username, /* The autovacuum launcher is done here */ if (IsAutoVacuumLauncherProcess()) - return true; /* result doesn't matter */ + return; /* * Start a new transaction here before first access to db, and get a @@ -706,12 +706,12 @@ InitPostgres(const char *in_dbname, Oid dboid, const char *username, /* * Perform client authentication if necessary, then figure out our - * postgres user id, and see if we are a superuser. + * postgres user ID, and see if we are a superuser. * - * In standalone mode and in the autovacuum process, we use a fixed id, - * otherwise we figure it out from the authenticated user name. + * In standalone mode and in autovacuum worker processes, we use a fixed + * ID, otherwise we figure it out from the authenticated user name. */ - if (bootstrap || autovacuum) + if (bootstrap || IsAutoVacuumWorkerProcess()) { InitializeSessionUserIdStandalone(); am_superuser = true; @@ -724,7 +724,7 @@ InitPostgres(const char *in_dbname, Oid dboid, const char *username, ereport(WARNING, (errcode(ERRCODE_UNDEFINED_OBJECT), errmsg("no roles are defined in this database system"), - errhint("You should immediately run CREATE USER \"%s\" CREATEUSER;.", + errhint("You should immediately run CREATE USER \"%s\" SUPERUSER;.", username))); } else @@ -768,6 +768,69 @@ InitPostgres(const char *in_dbname, Oid dboid, const char *username, (errcode(ERRCODE_TOO_MANY_CONNECTIONS), errmsg("connection limit exceeded for non-superusers"))); + /* + * Now process any command-line switches that were included in the startup + * packet, if we are in a regular backend. We couldn't do this before + * because we didn't know if client is a superuser. + */ + gucctx = am_superuser ? PGC_SUSET : PGC_BACKEND; + + if (MyProcPort != NULL && + MyProcPort->cmdline_options != NULL) + { + /* + * The maximum possible number of commandline arguments that could + * come from MyProcPort->cmdline_options is (strlen + 1) / 2; see + * pg_split_opts(). + */ + char **av; + int maxac; + int ac; + + maxac = 2 + (strlen(MyProcPort->cmdline_options) + 1) / 2; + + av = (char **) palloc(maxac * sizeof(char *)); + ac = 0; + + av[ac++] = "postgres"; + + /* Note this mangles MyProcPort->cmdline_options */ + pg_split_opts(av, &ac, MyProcPort->cmdline_options); + + av[ac] = NULL; + + Assert(ac < maxac); + + (void) process_postgres_switches(ac, av, gucctx); + } + + /* + * Process any additional GUC variable settings passed in startup packet. + * These are handled exactly like command-line variables. + */ + if (MyProcPort != NULL) + { + ListCell *gucopts = list_head(MyProcPort->guc_options); + + while (gucopts) + { + char *name; + char *value; + + name = lfirst(gucopts); + gucopts = lnext(gucopts); + + value = lfirst(gucopts); + gucopts = lnext(gucopts); + + SetConfigOption(name, value, gucctx, PGC_S_CLIENT); + } + } + + /* Apply PostAuthDelay as soon as we've read all options */ + if (PostAuthDelay > 0) + pg_usleep(PostAuthDelay * 1000000L); + /* * Initialize various default states that can't be set up until we've * selected the active user and gotten the right GUC settings. @@ -786,8 +849,6 @@ InitPostgres(const char *in_dbname, Oid dboid, const char *username, /* close the transaction we started above */ if (!bootstrap) CommitTransactionCommand(); - - return am_superuser; } diff --git a/src/include/miscadmin.h b/src/include/miscadmin.h index cd787b87da..ae73f91edd 100644 --- a/src/include/miscadmin.h +++ b/src/include/miscadmin.h @@ -13,7 +13,7 @@ * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/miscadmin.h,v 1.213 2009/08/29 19:26:51 tgl Exp $ + * $PostgreSQL: pgsql/src/include/miscadmin.h,v 1.214 2009/09/01 00:09:42 tgl Exp $ * * NOTES * some of the information in this file should be moved to other files. @@ -324,7 +324,7 @@ extern ProcessingMode Mode; /* in utils/init/postinit.c */ extern void pg_split_opts(char **argv, int *argcp, char *optstr); -extern bool InitPostgres(const char *in_dbname, Oid dboid, const char *username, +extern void InitPostgres(const char *in_dbname, Oid dboid, const char *username, char *out_dbname); extern void BaseInit(void); diff --git a/src/include/tcop/tcopprot.h b/src/include/tcop/tcopprot.h index 674e680284..b1c8b77bd5 100644 --- a/src/include/tcop/tcopprot.h +++ b/src/include/tcop/tcopprot.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/tcop/tcopprot.h,v 1.99 2009/08/29 19:26:52 tgl Exp $ + * $PostgreSQL: pgsql/src/include/tcop/tcopprot.h,v 1.100 2009/09/01 00:09:42 tgl Exp $ * * OLD COMMENTS * This file was created so that other c files could get the two @@ -62,6 +62,8 @@ extern void StatementCancelHandler(SIGNAL_ARGS); extern void FloatExceptionHandler(SIGNAL_ARGS); extern void prepare_for_client_read(void); extern void client_read_ended(void); +extern const char *process_postgres_switches(int argc, char *argv[], + GucContext ctx); extern int PostgresMain(int argc, char *argv[], const char *username); extern long get_stack_depth_rlimit(void); extern void ResetUsage(void);