diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c index 9b3c14399c..893a7b95cd 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.438 2004/11/20 00:48:58 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/tcop/postgres.c,v 1.439 2004/11/24 19:50:59 tgl Exp $ * * NOTES * this is the "main" module of the postgres backend and @@ -2205,7 +2205,7 @@ PostgresMain(int argc, char *argv[], const char *username) bool secure; int errs = 0; int debug_flag = -1; /* -1 means not given */ - List *guc_names = NIL; /* for possibly-SUSET options */ + List *guc_names = NIL; /* for SUSET options */ List *guc_values = NIL; GucContext ctx; GucSource gucsource; @@ -2456,8 +2456,15 @@ PostgresMain(int argc, char *argv[], const char *username) /* * s - report usage statistics (timings) after each query + * + * Since log options are SUSET, we need to postpone unless + * still in secure context */ - PendingConfigOption("log_statement_stats", "true"); + if (ctx == PGC_BACKEND) + PendingConfigOption("log_statement_stats", "true"); + else + SetConfigOption("log_statement_stats", "true", + ctx, gucsource); break; case 't': @@ -2490,7 +2497,12 @@ PostgresMain(int argc, char *argv[], const char *username) break; } if (tmp) - PendingConfigOption(tmp, "true"); + { + if (ctx == PGC_BACKEND) + PendingConfigOption(tmp, "true"); + else + SetConfigOption(tmp, "true", ctx, gucsource); + } break; case 'v': @@ -2527,7 +2539,14 @@ PostgresMain(int argc, char *argv[], const char *username) optarg))); } - PendingConfigOption(name, value); + /* + * If a SUSET option, must postpone evaluation, unless + * we are still reading secure switches. + */ + if (ctx == PGC_BACKEND && IsSuperuserConfigOption(name)) + PendingConfigOption(name, value); + else + SetConfigOption(name, value, ctx, gucsource); free(name); if (value) free(value); @@ -2540,6 +2559,32 @@ PostgresMain(int argc, char *argv[], const char *username) } } + /* + * 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); + + if (IsSuperuserConfigOption(name)) + PendingConfigOption(name, value); + else + SetConfigOption(name, value, PGC_BACKEND, PGC_S_CLIENT); + } + } + /* Acquire configuration parameters, unless inherited from postmaster */ if (!IsUnderPostmaster) { @@ -2677,10 +2722,8 @@ PostgresMain(int argc, char *argv[], const char *username) SetProcessingMode(NormalProcessing); /* - * Now that we know if client is a superuser, we can apply GUC options - * that came from the client. (For option switches that are definitely - * not SUSET, we just went ahead and applied them above, but anything - * that is or might be SUSET has to be postponed to here.) + * Now that we know if client is a superuser, we can try to apply SUSET + * GUC options that came from the client. */ ctx = am_superuser ? PGC_SUSET : PGC_USERSET; @@ -2703,41 +2746,19 @@ PostgresMain(int argc, char *argv[], const char *username) } } - /* - * Process any additional GUC variable settings passed in startup - * packet. - */ - 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); - } - - /* - * set up handler to log session end. - */ - if (IsUnderPostmaster && Log_disconnections) - on_proc_exit(log_disconnections, 0); - } - /* * Now all GUC states are fully set up. Report them to client if * appropriate. */ BeginReportingGUCOptions(); + /* + * Also set up handler to log session end; we have to wait till now + * to be sure Log_disconnections has its final value. + */ + if (IsUnderPostmaster && Log_disconnections) + on_proc_exit(log_disconnections, 0); + /* * Send this backend's cancellation info to the frontend. */ diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c index 581a96caa2..fd13c41a35 100644 --- a/src/backend/utils/misc/guc.c +++ b/src/backend/utils/misc/guc.c @@ -10,7 +10,7 @@ * Written by Peter Eisentraut . * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/utils/misc/guc.c,v 1.249 2004/11/14 19:35:33 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/utils/misc/guc.c,v 1.250 2004/11/24 19:51:03 tgl Exp $ * *-------------------------------------------------------------------- */ @@ -3864,6 +3864,21 @@ GetConfigOptionResetString(const char *name) return NULL; } +/* + * Detect whether the given configuration option can only be set by + * a superuser. + */ +bool +IsSuperuserConfigOption(const char *name) +{ + struct config_generic *record; + + record = find_option(name, ERROR); + /* On an unrecognized name, don't error, just return false. */ + if (record == NULL) + return false; + return (record->context == PGC_SUSET); +} /* diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h index f5f4a78fe4..786d696620 100644 --- a/src/include/utils/guc.h +++ b/src/include/utils/guc.h @@ -7,7 +7,7 @@ * Copyright (c) 2000-2004, PostgreSQL Global Development Group * Written by Peter Eisentraut . * - * $PostgreSQL: pgsql/src/include/utils/guc.h,v 1.56 2004/11/14 19:35:35 tgl Exp $ + * $PostgreSQL: pgsql/src/include/utils/guc.h,v 1.57 2004/11/24 19:51:05 tgl Exp $ *-------------------------------------------------------------------- */ #ifndef GUC_H @@ -44,9 +44,7 @@ * given backend once it's started, but they can vary across backends. * * SUSET options can be set at postmaster startup, with the SIGHUP - * mechanism, or from SQL if you're a superuser. These options cannot - * be set in the connection startup packet, because when it is processed - * we don't yet know if the user is a superuser. + * mechanism, or from SQL if you're a superuser. * * USERSET options can be set by anyone any time. */ @@ -177,6 +175,7 @@ extern void EmitWarningsOnPlaceholders(const char *className); extern const char *GetConfigOption(const char *name); extern const char *GetConfigOptionResetString(const char *name); +extern bool IsSuperuserConfigOption(const char *name); extern void ProcessConfigFile(GucContext context); extern void InitializeGUCOptions(void); extern bool SelectConfigFiles(const char *userDoption, const char *progname);