diff -u -r postgresql-7.3.2/src/backend/libpq/hba.c postgresql-7.3.2.ec/src/backend/libpq/hba.c --- postgresql-7.3.2/src/backend/libpq/hba.c Sat Dec 14 13:49:43 2002 +++ postgresql-7.3.2.ec/src/backend/libpq/hba.c Mon Feb 17 14:57:37 2003 @@ -35,6 +35,7 @@ #include "miscadmin.h" #include "nodes/pg_list.h" #include "storage/fd.h" +#include "utils/guc.h" #define IDENT_USERNAME_MAX 512 @@ -837,10 +838,22 @@ if (hba_lines) free_lines(&hba_lines); - /* Put together the full pathname to the config file. */ - bufsize = (strlen(DataDir) + strlen(CONF_FILE) + 2) * sizeof(char); - conf_file = (char *) palloc(bufsize); - snprintf(conf_file, bufsize, "%s/%s", DataDir, CONF_FILE); + /* Explicit HBA in config file */ + if(explicit_hbafile && strlen(explicit_hbafile)) + { + bufsize = strlen(explicit_hbafile)+1; + conf_file = (char *) palloc(bufsize); + strcpy(conf_file, explicit_hbafile); + } + else + { + char *confloc = (explicit_isdir) ? explicit_pgconfig : DataDir; + /* put together the full pathname to the config file */ + bufsize = (strlen(confloc) + strlen(CONF_FILE) + 2) * sizeof(char); + conf_file = (char *) palloc(bufsize); + snprintf(conf_file, bufsize, "%s/%s", confloc, CONF_FILE); + } + /* printf("hba_conf: %s\n", conf_file); */ file = AllocateFile(conf_file, "r"); if (file == NULL) @@ -979,10 +992,22 @@ if (ident_lines) free_lines(&ident_lines); - /* put together the full pathname to the map file */ - bufsize = (strlen(DataDir) + strlen(USERMAP_FILE) + 2) * sizeof(char); - map_file = (char *) palloc(bufsize); - snprintf(map_file, bufsize, "%s/%s", DataDir, USERMAP_FILE); + /* Explicit IDENT in config file */ + if(explicit_identfile && strlen(explicit_identfile)) + { + bufsize = strlen(explicit_identfile)+1; + map_file = (char *) palloc(bufsize); + strcpy(map_file, explicit_identfile); + } + else + { + /* put together the full pathname to the map file */ + char *confloc = (explicit_isdir) ? explicit_pgconfig : DataDir; + bufsize = (strlen(confloc) + strlen(USERMAP_FILE) + 2) * sizeof(char); + map_file = (char *) palloc(bufsize); + snprintf(map_file, bufsize, "%s/%s", confloc, USERMAP_FILE); + } + /* printf("ident_conf: %s\n", map_file); */ file = AllocateFile(map_file, "r"); if (file == NULL) diff -u -r postgresql-7.3.2/src/backend/postmaster/postmaster.c postgresql-7.3.2.ec/src/backend/postmaster/postmaster.c --- postgresql-7.3.2/src/backend/postmaster/postmaster.c Wed Jan 15 19:27:17 2003 +++ postgresql-7.3.2.ec/src/backend/postmaster/postmaster.c Mon Feb 17 12:14:12 2003 @@ -421,7 +421,7 @@ opterr = 1; - while ((opt = getopt(argc, argv, "A:a:B:b:c:D:d:Fh:ik:lm:MN:no:p:Ss-:")) != -1) + while ((opt = getopt(argc, argv, "A:a:B:b:C:c:D:d:Fh:ik:lm:MN:no:p:Ss-:")) != -1) { switch (opt) { @@ -441,6 +441,9 @@ case 'b': /* Can no longer set the backend executable file to use. */ break; + case 'C': // MLW + explicit_pgconfig = optarg; + break; case 'D': potential_DataDir = optarg; break; @@ -564,13 +567,23 @@ ExitPostmaster(1); } - /* - * Now we can set the data directory, and then read postgresql.conf. - */ - checkDataDir(potential_DataDir); /* issues error messages */ - SetDataDir(potential_DataDir); - - ProcessConfigFile(PGC_POSTMASTER); + if(explicit_pgconfig) + { + ProcessConfigFile(PGC_POSTMASTER); + if(!potential_DataDir && pgdatadir) + potential_DataDir = pgdatadir; + checkDataDir(potential_DataDir); /* issues error messages */ + SetDataDir(potential_DataDir); + } + else + { + /* + * Now we can set the data directory, and then read postgresql.conf. + */ + checkDataDir(potential_DataDir); /* issues error messages */ + SetDataDir(potential_DataDir); + ProcessConfigFile(PGC_POSTMASTER); + } /* * Check for invalid combinations of GUC settings. diff -u -r postgresql-7.3.2/src/backend/utils/misc/guc-file.c postgresql-7.3.2.ec/src/backend/utils/misc/guc-file.c --- postgresql-7.3.2/src/backend/utils/misc/guc-file.c Mon Feb 3 15:22:34 2003 +++ postgresql-7.3.2.ec/src/backend/utils/misc/guc-file.c Mon Feb 17 14:58:11 2003 @@ -2,7 +2,6 @@ /* Scanner skeleton version: * $Header: /home/daffy/u0/vern/flex/RCS/flex.skl,v 2.91 96/09/10 16:58:48 vern Exp $ - * $FreeBSD: src/usr.bin/lex/flex.skl,v 1.4 1999/10/27 07:56:44 obrien Exp $ */ #define FLEX_SCANNER @@ -10,6 +9,7 @@ #define YY_FLEX_MINOR_VERSION 5 #include +#include /* cfront 1.2 defines "c_plusplus" instead of "__cplusplus" */ @@ -23,7 +23,6 @@ #ifdef __cplusplus #include -#include /* Use prototypes in function declarations. */ #define YY_USE_PROTOS @@ -443,7 +442,7 @@ char *GUC_scanstr(char *); #define YY_NEVER_INTERACTIVE 1 #define YY_NO_UNPUT 1 -#line 447 "lex.GUC_yy.c" +#line 446 "lex.GUC_yy.c" /* Macros after this point can all be overridden by user definitions in * section 1. @@ -591,13 +590,13 @@ YY_DECL { register GUC_yy_state_type GUC_yy_current_state; - register char *GUC_yy_cp, *GUC_yy_bp; + register char *GUC_yy_cp = NULL, *GUC_yy_bp = NULL; register int GUC_yy_act; #line 71 "guc-file.l" -#line 601 "lex.GUC_yy.c" +#line 600 "lex.GUC_yy.c" if ( GUC_yy_init ) { @@ -738,7 +737,7 @@ #line 86 "guc-file.l" ECHO; YY_BREAK -#line 742 "lex.GUC_yy.c" +#line 741 "lex.GUC_yy.c" case YY_STATE_EOF(INITIAL): GUC_yyterminate(); @@ -1302,11 +1301,6 @@ } -#ifndef YY_ALWAYS_INTERACTIVE -#ifndef YY_NEVER_INTERACTIVE -extern int isatty YY_PROTO(( int )); -#endif -#endif #ifdef YY_USE_PROTOS void GUC_yy_init_buffer( YY_BUFFER_STATE b, FILE *file ) @@ -1658,51 +1652,27 @@ } } +#define ELEVEL_FROM_CONTEXT(ctx) (ctx == PGC_SIGHUP) ? DEBUG3 : ERROR -/* - * Official function to read and process the configuration file. The - * parameter indicates in what context the file is being read - * (postmaster startup, backend startup, or SIGHUP). All options - * mentioned in the configuration file are set to new values. This - * function does not return if an error occurs. If an error occurs, no - * values will be changed. - */ -void -ProcessConfigFile(GucContext context) +static void +ReadConfigFile(char *filename, GucContext context) { int token, parse_state; char *opt_name, *opt_value; - char *filename; struct name_value_pair *item, *head, *tail; - int elevel; - FILE * fp; - - Assert(context == PGC_POSTMASTER || context == PGC_BACKEND - || context == PGC_SIGHUP); - Assert(DataDir); - elevel = (context == PGC_SIGHUP) ? DEBUG3 : ERROR; + FILE *fp; + int elevel = ELEVEL_FROM_CONTEXT(context); - /* - * Open file - */ - filename = malloc(strlen(DataDir) + strlen(CONFIG_FILENAME) + 2); - if (filename == NULL) - { - elog(elevel, "out of memory"); - return; - } - sprintf(filename, "%s/" CONFIG_FILENAME, DataDir); - - fp = AllocateFile(filename, "r"); - if (!fp) - { + fp = AllocateFile(filename, "r"); + if (!fp) + { + /* File not found is fine */ + if (errno != ENOENT) + elog(elevel, "could not read configuration file %s: %s", + filename, strerror(errno)); free(filename); - /* File not found is fine */ - if (errno != ENOENT) - elog(elevel, "could not read configuration file `" CONFIG_FILENAME "': %s", strerror(errno)); return; - } - + } /* * Parse */ @@ -1731,7 +1701,8 @@ token = GUC_yylex(); if (token != GUC_ID && token != GUC_STRING && - token != GUC_INTEGER && token != GUC_REAL && + token != GUC_INTEGER && + token != GUC_REAL && token != GUC_UNQUOTED_STRING) goto parse_error; opt_value = strdup(GUC_yytext); @@ -1775,7 +1746,6 @@ } FreeFile(fp); - free(filename); /* * Check if all options are valid @@ -1798,7 +1768,6 @@ parse_error: FreeFile(fp); - free(filename); free_name_value_list(head); elog(elevel, CONFIG_FILENAME ":%u: syntax error, token=\"%s\"", ConfigFileLineno,GUC_yytext); @@ -1806,12 +1775,78 @@ out_of_memory: FreeFile(fp); - free(filename); free_name_value_list(head); elog(elevel, "out of memory"); return; } +/* + * Official function to read and process the configuration file. The + * parameter indicates in what context the file is being read + * (postmaster startup, backend startup, or SIGHUP). All options + * mentioned in the configuration file are set to new values. This + * function does not return if an error occurs. If an error occurs, no + * values will be changed. + */ +void +ProcessConfigFile(GucContext context) +{ + char *filename; + + Assert(context == PGC_POSTMASTER || context == PGC_BACKEND + || context == PGC_SIGHUP); + /* Added for explicit config file */ + if(explicit_pgconfig) + { + struct stat sb; + + if(stat(explicit_pgconfig, &sb)!=0) + { + int elevel = (context == PGC_SIGHUP) ? DEBUG3 : ERROR; + elog(elevel, "Invalid configuration parameter"); + return ; + } + + + if((sb.st_mode & S_IFDIR) == S_IFDIR) + { + /* This will cause a small one time memory leak + * if the user also specifies hba_conf, + * ident_conf, and data_dir + */ + filename = malloc(strlen(explicit_pgconfig) + strlen(CONFIG_FILENAME) + 2); + sprintf(filename, "%s/%s", explicit_pgconfig, CONFIG_FILENAME); + explicit_isdir = true; + } + else + { + /* + * Use explicit file + */ + filename = strdup(explicit_pgconfig); + } + } + else + { + /* + * Use environmental config + */ + filename = malloc(strlen(DataDir) + strlen(CONFIG_FILENAME) + 2); + sprintf(filename, "%s/%s", DataDir, CONFIG_FILENAME); + } + + if (filename == NULL) + { + int elevel = (context == PGC_SIGHUP) ? DEBUG3 : ERROR; + elog(elevel, "out of memory"); + return; + } + /* printf("Using: %s\n", filename); */ + + ReadConfigFile(filename, context); + + free(filename); +} /* ---------------- diff -u -r postgresql-7.3.2/src/backend/utils/misc/guc-file.l postgresql-7.3.2.ec/src/backend/utils/misc/guc-file.l --- postgresql-7.3.2/src/backend/utils/misc/guc-file.l Tue Jul 30 12:33:08 2002 +++ postgresql-7.3.2.ec/src/backend/utils/misc/guc-file.l Mon Feb 17 14:58:07 2003 @@ -116,51 +116,27 @@ } } +#define ELEVEL_FROM_CONTEXT(ctx) (ctx == PGC_SIGHUP) ? DEBUG3 : ERROR -/* - * Official function to read and process the configuration file. The - * parameter indicates in what context the file is being read - * (postmaster startup, backend startup, or SIGHUP). All options - * mentioned in the configuration file are set to new values. This - * function does not return if an error occurs. If an error occurs, no - * values will be changed. - */ -void -ProcessConfigFile(GucContext context) +static void +ReadConfigFile(char *filename, GucContext context) { int token, parse_state; char *opt_name, *opt_value; - char *filename; struct name_value_pair *item, *head, *tail; - int elevel; - FILE * fp; - - Assert(context == PGC_POSTMASTER || context == PGC_BACKEND - || context == PGC_SIGHUP); - Assert(DataDir); - elevel = (context == PGC_SIGHUP) ? DEBUG3 : ERROR; + FILE *fp; + int elevel = ELEVEL_FROM_CONTEXT(context); - /* - * Open file - */ - filename = malloc(strlen(DataDir) + strlen(CONFIG_FILENAME) + 2); - if (filename == NULL) - { - elog(elevel, "out of memory"); - return; - } - sprintf(filename, "%s/" CONFIG_FILENAME, DataDir); - - fp = AllocateFile(filename, "r"); - if (!fp) - { + fp = AllocateFile(filename, "r"); + if (!fp) + { + /* File not found is fine */ + if (errno != ENOENT) + elog(elevel, "could not read configuration file %s: %s", + filename, strerror(errno)); free(filename); - /* File not found is fine */ - if (errno != ENOENT) - elog(elevel, "could not read configuration file `" CONFIG_FILENAME "': %s", strerror(errno)); return; - } - + } /* * Parse */ @@ -189,7 +165,8 @@ token = yylex(); if (token != GUC_ID && token != GUC_STRING && - token != GUC_INTEGER && token != GUC_REAL && + token != GUC_INTEGER && + token != GUC_REAL && token != GUC_UNQUOTED_STRING) goto parse_error; opt_value = strdup(yytext); @@ -233,7 +210,6 @@ } FreeFile(fp); - free(filename); /* * Check if all options are valid @@ -256,7 +232,6 @@ parse_error: FreeFile(fp); - free(filename); free_name_value_list(head); elog(elevel, CONFIG_FILENAME ":%u: syntax error, token=\"%s\"", ConfigFileLineno,yytext); @@ -264,12 +239,78 @@ out_of_memory: FreeFile(fp); - free(filename); free_name_value_list(head); elog(elevel, "out of memory"); return; } +/* + * Official function to read and process the configuration file. The + * parameter indicates in what context the file is being read + * (postmaster startup, backend startup, or SIGHUP). All options + * mentioned in the configuration file are set to new values. This + * function does not return if an error occurs. If an error occurs, no + * values will be changed. + */ +void +ProcessConfigFile(GucContext context) +{ + char *filename; + + Assert(context == PGC_POSTMASTER || context == PGC_BACKEND + || context == PGC_SIGHUP); + + /* Added for explicit config file */ + if(explicit_pgconfig) + { + struct stat sb; + + if(stat(explicit_pgconfig, &sb)!=0) + { + int elevel = (context == PGC_SIGHUP) ? DEBUG3 : ERROR; + elog(elevel, "Invalid configuration parameter"); + return ; + } + + + if((sb.st_mode & S_IFDIR) == S_IFDIR) + { + /* This will cause a small one time memory leak + * if the user also specifies hba_conf, + * ident_conf, and data_dir + */ + filename = malloc(strlen(explicit_pgconfig) + strlen(CONFIG_FILENAME) + 2); + sprintf(filename, "%s/%s", explicit_pgconfig, CONFIG_FILENAME); + explicit_isdir = true; + } + else + { + /* + * Use explicit file + */ + filename = strdup(explicit_pgconfig); + } + } + else + { + /* + * Use environmental config + */ + filename = malloc(strlen(DataDir) + strlen(CONFIG_FILENAME) + 2); + sprintf(filename, "%s/%s", DataDir, CONFIG_FILENAME); + } + + if (filename == NULL) + { + int elevel = (context == PGC_SIGHUP) ? DEBUG3 : ERROR; + elog(elevel, "out of memory"); + return; + } + /* printf("Using: %s\n", filename); */ + ReadConfigFile(filename, context); + + free(filename); +} /* ---------------- diff -u -r postgresql-7.3.2/src/backend/utils/misc/guc.c postgresql-7.3.2.ec/src/backend/utils/misc/guc.c --- postgresql-7.3.2/src/backend/utils/misc/guc.c Tue Jan 28 13:04:13 2003 +++ postgresql-7.3.2.ec/src/backend/utils/misc/guc.c Mon Feb 17 14:38:34 2003 @@ -51,6 +51,12 @@ #include "utils/pg_locale.h" #include "pgstat.h" +/* Added for config file only startup MLW */ +char *explicit_pgconfig = NULL; +char *explicit_hbafile = NULL; +char *explicit_identfile = NULL; +bool explicit_isdir=false; +char *pgdatadir = NULL; /* XXX these should be in other modules' header files */ extern bool Log_connections; @@ -113,6 +119,7 @@ char *client_min_messages_str = NULL; const char client_min_messages_str_default[] = "notice"; +static void ReadConfigFile(char *filename, GucContext context); #ifndef PG_KRB_SRVTAB #define PG_KRB_SRVTAB "" @@ -146,7 +153,8 @@ PGC_BOOL, PGC_INT, PGC_REAL, - PGC_STRING + PGC_STRING, + PGC_FUNCTION }; /* Generic fields applicable to all types of variables */ @@ -239,6 +247,13 @@ char *tentative_val; }; +struct config_function +{ + struct config_generic gen; + void (*function)(char *param, GucContext context); +}; + + /* Macros for freeing malloc'd pointers only if appropriate to do so */ /* Some of these tests are probably redundant, but be safe ... */ #define SET_STRING_VARIABLE(rec, newval) \ @@ -853,10 +868,32 @@ }, { + {"data_dir", PGC_POSTMASTER}, &pgdatadir, + "", NULL, NULL + }, + + { + {"hba_conf", PGC_POSTMASTER}, &explicit_hbafile, + "", NULL, NULL + }, + + { + {"ident_conf", PGC_POSTMASTER}, &explicit_identfile, + "", NULL, NULL + }, + + { {NULL, 0}, NULL, NULL, NULL, NULL } }; + +static struct config_function ConfigureFunctions[] = +{ + { {"include", PGC_POSTMASTER}, ReadConfigFile}, + { {NULL,0}, NULL} +}; + /******** end of options list ********/ @@ -919,6 +956,12 @@ conf->gen.vartype = PGC_STRING; num_vars++; } + for(i = 0; ConfigureFunctions[i].gen.name; i++) + { + struct config_function *conf = &ConfigureFunctions[i]; + conf->gen.vartype = PGC_FUNCTION; + num_vars++; + } guc_vars = (struct config_generic **) malloc(num_vars * sizeof(struct config_generic *)); @@ -939,6 +982,9 @@ for (i = 0; ConfigureNamesString[i].gen.name; i++) guc_vars[num_vars++] = &ConfigureNamesString[i].gen; + for (i = 0; ConfigureFunctions[i].gen.name; i++) + guc_vars[num_vars++] = &ConfigureFunctions[i].gen; + qsort((void *) guc_vars, num_vars, sizeof(struct config_generic *), guc_var_compare); @@ -1135,6 +1181,8 @@ conf->session_val = str; break; } + case PGC_FUNCTION: /* Nothing to do */ + break; } } @@ -1280,6 +1328,8 @@ guc_dirty = true; break; } + case PGC_FUNCTION: /* Nothing to do */ + break; } } } @@ -1421,6 +1471,8 @@ conf->gen.status = 0; break; } + case PGC_FUNCTION: /* Nothing to do */ + break; } } @@ -1684,6 +1736,17 @@ */ switch (record->vartype) { + case PGC_FUNCTION: + if(!DoIt) + { + /* During the "checking" stage of configuration + * read, run functions + */ + struct config_function *fn = + (struct config_function *)record; + fn->function((char *)value, context); + } + break; case PGC_BOOL: { struct config_bool *conf = (struct config_bool *) record; @@ -2063,6 +2126,9 @@ case PGC_STRING: return *((struct config_string *) record)->variable; + case PGC_FUNCTION: + /* Should never really happen */ + return NULL; } return NULL; } @@ -2097,6 +2163,9 @@ case PGC_STRING: return ((struct config_string *) record)->reset_val; + case PGC_FUNCTION: + /* Should never really happen */ + return NULL; } return NULL; } diff -u -r postgresql-7.3.2/src/backend/utils/misc/postgresql.conf.sample postgresql-7.3.2.ec/src/backend/utils/misc/postgresql.conf.sample --- postgresql-7.3.2/src/backend/utils/misc/postgresql.conf.sample Mon Jan 27 22:44:09 2003 +++ postgresql-7.3.2.ec/src/backend/utils/misc/postgresql.conf.sample Mon Feb 17 12:14:12 2003 @@ -23,6 +23,21 @@ #======================================================================== +# Allows PostgreSQL to include another file +# include = '/somedir/pgdefs.conf' + +# Allows PostgreSQL to use a pg_hba.conf file +# which is not in the database directory. +# hba_conf = '/etc/postgres/pg_hba.conf' + +# Allows PostgreSQL to use a pg_ident.conf file +# which is not in the database directory. +# ident_conf = '/etc/postgres/pg_ident.conf' + +# Allows Postgres to find its data directory +# from this configuration file. +# data_dir = '/RAID0/postgres' + # # Connection Parameters diff -u -r postgresql-7.3.2/src/include/utils/guc.h postgresql-7.3.2.ec/src/include/utils/guc.h --- postgresql-7.3.2/src/include/utils/guc.h Mon Oct 21 14:57:35 2002 +++ postgresql-7.3.2.ec/src/include/utils/guc.h Mon Feb 17 14:40:57 2003 @@ -137,5 +137,11 @@ extern char *client_min_messages_str; extern const char client_min_messages_str_default[]; +/* Added MLW */ +extern char *explicit_pgconfig; +extern char *explicit_hbafile; +extern char *explicit_identfile; +extern bool explicit_isdir; +extern char *pgdatadir; #endif /* GUC_H */