diff -u -r postgresql-7.4.2/src/backend/commands/dbcommands.c postgresql-7.4.2-pgec/src/backend/commands/dbcommands.c --- postgresql-7.4.2/src/backend/commands/dbcommands.c 2003-09-28 20:05:24.000000000 -0400 +++ postgresql-7.4.2-pgec/src/backend/commands/dbcommands.c 2004-05-12 13:12:26.000000000 -0400 @@ -865,7 +865,6 @@ return retval; } - static char * resolve_alt_dbpath(const char *dbpath, Oid dboid) { @@ -892,17 +891,17 @@ else { /* must be environment variable */ - char *var = getenv(dbpath); + char *var = GetTablespacePath(dbpath); if (!var) ereport(ERROR, (errcode(ERRCODE_UNDEFINED_OBJECT), - errmsg("postmaster environment variable \"%s\" not found", + errmsg("postmaster tablespace \"%s\" not found", dbpath))); if (!is_absolute_path(var)) ereport(ERROR, (errcode(ERRCODE_INVALID_NAME), - errmsg("postmaster environment variable \"%s\" must be absolute path", + errmsg("postmaster tablespace \"%s\" must be absolute path", dbpath))); prefix = var; } Only in postgresql-7.4.2-pgec/src/backend/commands: dbcommands.c~ diff -u -r postgresql-7.4.2/src/backend/libpq/hba.c postgresql-7.4.2-pgec/src/backend/libpq/hba.c --- postgresql-7.4.2/src/backend/libpq/hba.c 2003-12-05 10:50:39.000000000 -0500 +++ postgresql-7.4.2-pgec/src/backend/libpq/hba.c 2004-04-09 16:51:14.000000000 -0400 @@ -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 @@ -957,10 +958,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) @@ -1103,10 +1116,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.4.2/src/backend/postmaster/postmaster.c postgresql-7.4.2-pgec/src/backend/postmaster/postmaster.c --- postgresql-7.4.2/src/backend/postmaster/postmaster.c 2004-02-23 15:46:16.000000000 -0500 +++ postgresql-7.4.2-pgec/src/backend/postmaster/postmaster.c 2004-05-12 12:18:17.000000000 -0400 @@ -301,6 +301,31 @@ #define ShutdownDataBase() SSDataBase(BS_XLOG_SHUTDOWN) +static bool +checkConfigDir(const char *checkdir) +{ + char path[MAXPGPATH]; + struct stat stat_buf; + + if (checkdir == NULL) /* let, checkDataDir handle this */ + return FALSE; + + if (stat(checkdir, &stat_buf) == -1) /* ditto */ + return FALSE; + + if(S_ISREG(stat_buf.st_mode)) /* It's a regular file, so assume it's an explict */ + { + return TRUE; + } + else if(S_ISDIR(stat_buf.st_mode)) /* It's a directory, is it a config or system dir */ + { + snprintf(path, sizeof(path), "%s/global/pg_control", checkdir); + /* If this is not found, then, hey it wasn't going to work as a data dir either. */ + if(stat(path, &stat_buf) == -1) + return TRUE; + } + return FALSE; +} static void checkDataDir(const char *checkdir) { @@ -385,6 +410,7 @@ int status; char original_extraoptions[MAXPGPATH]; char *potential_DataDir = NULL; + char *potential_pidfile=NULL; int i; *original_extraoptions = '\0'; @@ -448,7 +474,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:R:Ss-:")) != -1) { switch (opt) { @@ -468,6 +494,11 @@ case 'b': /* Can no longer set the backend executable file to use. */ break; +#if 0 + case 'C': // MLW + explicit_pgconfig = optarg; + break; +#endif case 'D': potential_DataDir = optarg; break; @@ -532,6 +563,11 @@ case 'p': SetConfigOption("port", optarg, PGC_POSTMASTER, PGC_S_ARGV); break; + case 'R': /* + * Write PID to a file for FHS compatibility + */ + potential_pidfile = optarg; + break; case 'S': /* @@ -600,13 +636,42 @@ 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(checkConfigDir(potential_DataDir)) + { + /* potential_DataDir failed checks for a postgresql + cluster, so assume its just a config dir */ + explicit_pgconfig = potential_DataDir; + potential_DataDir=NULL; + ProcessConfigFile(PGC_POSTMASTER); + if(!potential_DataDir && pgdatadir) + potential_DataDir = pgdatadir; + checkDataDir(potential_DataDir); /* issues error messages */ + SetDataDir(potential_DataDir); + } + else // Do as always + { + /* + * 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(potential_pidfile == NULL) + potential_pidfile = runtime_pidfile; + + if(potential_pidfile) + { + FILE *fpidfile = fopen(potential_pidfile, "w"); + if(fpidfile) + { + fprintf(fpidfile, "%d\n", MyProcPid); + fclose(fpidfile); + } + } + #ifdef EXEC_BACKEND write_nondefault_variables(PGC_POSTMASTER); #endif @@ -973,6 +1038,7 @@ #endif printf(gettext(" -B NBUFFERS number of shared buffers\n")); printf(gettext(" -c NAME=VALUE set run-time parameter\n")); + printf(gettext(" -C pg.conf Location of configuration file\n")); printf(gettext(" -d 1-5 debugging level\n")); printf(gettext(" -D DATADIR database directory\n")); printf(gettext(" -F turn fsync off\n")); Only in postgresql-7.4.2-pgec/src/backend/postmaster: postmaster.c~ diff -u -r postgresql-7.4.2/src/backend/utils/misc/database.c postgresql-7.4.2-pgec/src/backend/utils/misc/database.c --- postgresql-7.4.2/src/backend/utils/misc/database.c 2003-08-03 22:40:08.000000000 -0400 +++ postgresql-7.4.2-pgec/src/backend/utils/misc/database.c 2004-05-12 12:58:55.000000000 -0400 @@ -24,9 +24,126 @@ #include "miscadmin.h" #include "utils/syscache.h" - static bool PhonyHeapTupleSatisfiesNow(HeapTupleHeader tuple); +typedef struct _PGTABLESP +{ + char *name; + char *path; +}PGTABLESP; + +static int pg_tablespace_count = 0; +static PGTABLESP pg_tablespace[MAX_PG_TABLESPACES]; + +// Parameter should come in like this: +// NAME:/path +void SetTablespace(const char *parameter) +{ + char name[MAXPGPATH]; + char path[MAXPGPATH]; + int nname; + int npath; + int i; + + char *pstart = strchr(parameter, ':'); + + // Make sure we have space + if(pg_tablespace_count >= MAX_PG_TABLESPACES ) + { + char buffer[MAXPGPATH]; + snprintf(buffer, sizeof(buffer),"Too many tablespaces specified in configuration file %d >= %d", + pg_tablespace_count, MAX_PG_TABLESPACES); + elog(ERROR, buffer); + return; + } + // Split NAME:PATH + if(!pstart) + { + char buffer[MAXPGPATH]; + snprintf(buffer,sizeof(buffer),"invalid tablespace information: %s", parameter); + elog(ERROR, buffer); + return; + } + + pstart++; + nname = pstart - parameter; + + // Check that PATH is an absolute path + if (!is_absolute_path(pstart)) + { + char buffer[MAXPGPATH]; + snprintf(buffer,sizeof(buffer),"invalid tablespace path: %s", pstart); + elog(ERROR, buffer); + return; + } + npath = strlen(pstart)+1; + + if((nname >= sizeof(name))||(npath >= sizeof(path) )) + { + char buffer[MAXPGPATH]; + snprintf(buffer,sizeof(buffer),"Tablespace name/path too long: %s", parameter); + elog(ERROR, buffer); + return; + } + memcpy(name, parameter, nname); + memcpy(path, pstart, npath); + + name[nname-1]=0; + path[npath-1]=0; + + for(i=0; i < pg_tablespace_count; i++) + { + if(strcasecmp(pg_tablespace[i].name, name) == 0) + { + /* User error, or called to reload settings */ + if(strcasecmp(pg_tablespace[i].path, path) !=0) + { + /* Path changed? Should we allow this? Oh, well, do it + * until someone says its a bug */ + char *oldpath = pg_tablespace[i].path; + pg_tablespace[i].path = strdup(path); + snprintf(path,sizeof(path), + "Tablespace %s changed from '%s' to '%s'", + pg_tablespace[i].name, + oldpath, + pg_tablespace[i].path); + elog(WARNING, path); + free(oldpath); + return; + } + else + { + /* found it, it hasn't changed, so who cares? */ + return; + } + } + + } + /* If here, it wasn't in out list of tablespaces */ + pg_tablespace[pg_tablespace_count].name = strdup(name); + pg_tablespace[pg_tablespace_count].path = strdup(path); + { + snprintf(path,sizeof(path), + "Tablespace added: %s='%s'", + pg_tablespace[pg_tablespace_count].name, + pg_tablespace[pg_tablespace_count].path); + elog(LOG, path); + } + pg_tablespace_count++; +} + +char *GetTablespacePath(const char *name) +{ + int i; + + for(i=0; i < pg_tablespace_count; i++) + { + if(strcasecmp(name, pg_tablespace[i].name)==0) + return pg_tablespace[i].path; + } + // If here, must not be a volume in the config file, use env + return getenv(name); +} /* * ExpandDatabasePath resolves a proposed database path (obtained from @@ -64,16 +181,16 @@ /* path delimiter somewhere? then has leading environment variable */ else if ((cp = first_path_separator(dbpath)) != NULL) { - const char *envvar; + const char *volpath; len = cp - dbpath; strncpy(buf, dbpath, len); buf[len] = '\0'; - envvar = getenv(buf); - if (envvar == NULL) + volpath = GetTablespacePath(buf); + if (volpath == NULL) return NULL; - snprintf(buf, sizeof(buf), "%s/base/%s", envvar, (cp + 1)); + snprintf(buf, sizeof(buf), "%s/base/%s", volpath, (cp + 1)); } else { Only in postgresql-7.4.2-pgec/src/backend/utils/misc: database.c~ diff -u -r postgresql-7.4.2/src/backend/utils/misc/guc.c postgresql-7.4.2-pgec/src/backend/utils/misc/guc.c --- postgresql-7.4.2/src/backend/utils/misc/guc.c 2004-02-23 15:46:16.000000000 -0500 +++ postgresql-7.4.2-pgec/src/backend/utils/misc/guc.c 2004-05-12 13:06:23.000000000 -0400 @@ -55,6 +55,13 @@ #include "utils/pg_locale.h" #include "pgstat.h" +/* Added for config file only startup MLW */ +char *runtime_pidfile=NULL; +char *explicit_pgconfig = NULL; +char *explicit_hbafile = NULL; +char *explicit_identfile = NULL; +bool explicit_isdir=false; +char *pgdatadir = NULL; #ifndef PG_KRB_SRVTAB #define PG_KRB_SRVTAB "" @@ -96,6 +103,9 @@ bool interactive); static bool assign_phony_autocommit(bool newval, bool doit, bool interactive); +static void ReadConfigFile(char *filename, GucContext context); + +static void SetConfigTablespace(char *parameter, GucContext context); /* * Debugging options @@ -156,6 +166,13 @@ static char *XactIsoLevel_string; +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) \ @@ -314,7 +331,8 @@ /* PGC_BOOL */ "bool", /* PGC_INT */ "integer", /* PGC_REAL */ "real", - /* PGC_STRING */ "string" + /* PGC_STRING */ "string", + /* PGC_FUNCTION */ "function" }; @@ -1578,6 +1596,24 @@ &XLOG_sync_method, XLOG_sync_method_default, assign_xlog_sync_method, NULL }, + { + {"pgdata", PGC_POSTMASTER, 0, gettext_noop("Configures data directory"), NULL}, + &pgdatadir, "", NULL, NULL + }, + + { + {"hba_conf", PGC_SIGHUP, 0, gettext_noop("loads hba file"), NULL}, + &explicit_hbafile, "", NULL, NULL + }, + + { + {"ident_conf", PGC_SIGHUP, 0, gettext_noop("Loads ident file"), NULL}, + &explicit_identfile, "", NULL, NULL + }, + { + {"runtime_pidfile", PGC_POSTMASTER, 0, gettext_noop("Writes PID to external file"), NULL}, + &runtime_pidfile, "", NULL, NULL + }, /* End-of-list marker */ { @@ -1585,8 +1621,20 @@ } }; +void SetConfigTablespace(char *parameter, GucContext context) +{ + SetTablespace(parameter); +} + /******** end of options list ********/ +static struct config_function ConfigureFunctions[] = +{ + { {"include", PGC_POSTMASTER}, ReadConfigFile}, + { {"tablespace", PGC_SIGHUP}, SetConfigTablespace}, + { {NULL,0}, NULL} +}; + /* * Actual lookup of variables is done through this single, sorted array. @@ -1650,6 +1698,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 *)); @@ -1672,6 +1726,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); @@ -1882,6 +1939,8 @@ conf->session_val = str; break; } + case PGC_FUNCTION: /* Nothing to do */ + break; } } @@ -2033,6 +2092,8 @@ guc_dirty = true; break; } + case PGC_FUNCTION: /* Nothing to do */ + break; } if (gconf->flags & GUC_REPORT) @@ -2188,6 +2249,8 @@ conf->gen.status = 0; break; } + case PGC_FUNCTION: /* Nothing to do */ + break; } if (changed && (gconf->flags & GUC_REPORT)) @@ -2533,6 +2596,17 @@ */ switch (record->vartype) { + case PGC_FUNCTION: + if(!changeVal) + { + /* 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; @@ -3029,6 +3103,9 @@ case PGC_STRING: return *((struct config_string *) record)->variable; + case PGC_FUNCTION: + /* Should never really happen */ + return NULL; } return NULL; } @@ -3065,6 +3142,9 @@ case PGC_STRING: return ((struct config_string *) record)->reset_val; + case PGC_FUNCTION: + /* Should never really happen */ + return NULL; } return NULL; } @@ -4381,3 +4461,4 @@ #include "guc-file.c" + Only in postgresql-7.4.2-pgec/src/backend/utils/misc: guc.c~ diff -u -r postgresql-7.4.2/src/backend/utils/misc/guc-file.c postgresql-7.4.2-pgec/src/backend/utils/misc/guc-file.c --- postgresql-7.4.2/src/backend/utils/misc/guc-file.c 2004-03-07 20:48:38.000000000 -0500 +++ postgresql-7.4.2-pgec/src/backend/utils/misc/guc-file.c 2004-05-12 11:57:01.000000000 -0400 @@ -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. @@ -597,7 +596,7 @@ #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 ) @@ -1667,34 +1661,17 @@ * 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) ? DEBUG4 : ERROR; - /* - * Open file - */ - filename = malloc(strlen(DataDir) + strlen(CONFIG_FILENAME) + 2); - if (filename == NULL) - { - ereport(elevel, - (errcode(ERRCODE_OUT_OF_MEMORY), - errmsg("out of memory"))); - return; - } - sprintf(filename, "%s/" CONFIG_FILENAME, DataDir); - fp = AllocateFile(filename, "r"); if (!fp) { @@ -1735,7 +1712,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); @@ -1779,7 +1757,6 @@ } FreeFile(fp); - free(filename); /* * Check if all options are valid @@ -1802,7 +1779,6 @@ parse_error: FreeFile(fp); - free(filename); free_name_value_list(head); ereport(elevel, (errcode(ERRCODE_SYNTAX_ERROR), @@ -1820,6 +1796,74 @@ 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.4.2/src/backend/utils/misc/guc-file.l postgresql-7.4.2-pgec/src/backend/utils/misc/guc-file.l --- postgresql-7.4.2/src/backend/utils/misc/guc-file.l 2003-09-25 02:58:05.000000000 -0400 +++ postgresql-7.4.2-pgec/src/backend/utils/misc/guc-file.l 2004-05-12 11:54:05.000000000 -0400 @@ -125,34 +125,17 @@ * 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) ? DEBUG4 : ERROR; - /* - * Open file - */ - filename = malloc(strlen(DataDir) + strlen(CONFIG_FILENAME) + 2); - if (filename == NULL) - { - ereport(elevel, - (errcode(ERRCODE_OUT_OF_MEMORY), - errmsg("out of memory"))); - return; - } - sprintf(filename, "%s/" CONFIG_FILENAME, DataDir); - fp = AllocateFile(filename, "r"); if (!fp) { @@ -193,7 +176,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); @@ -237,7 +221,6 @@ } FreeFile(fp); - free(filename); /* * Check if all options are valid @@ -260,7 +243,6 @@ parse_error: FreeFile(fp); - free(filename); free_name_value_list(head); ereport(elevel, (errcode(ERRCODE_SYNTAX_ERROR), @@ -278,6 +260,74 @@ 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.4.2/src/backend/utils/misc/postgresql.conf.sample postgresql-7.4.2-pgec/src/backend/utils/misc/postgresql.conf.sample --- postgresql-7.4.2/src/backend/utils/misc/postgresql.conf.sample 2003-10-07 23:49:38.000000000 -0400 +++ postgresql-7.4.2-pgec/src/backend/utils/misc/postgresql.conf.sample 2004-05-12 10:37:21.000000000 -0400 @@ -20,6 +20,29 @@ # to SIGHUP the postmaster for the changes to take effect, or use # "pg_ctl reload". +# 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. +# pgdata = '/RAID0/postgres' + +# Allows postgres to know where named tablespaces +# are located. +#tablespace='NAME:/path' + +# Allows Postgres to write a small file +# containing a number, on one line, that +# has its PID. This is used for init scripts +# runtime_pidfile= '/var/run/postgresql.pid' #--------------------------------------------------------------------------- # CONNECTIONS AND AUTHENTICATION diff -u -r postgresql-7.4.2/src/include/miscadmin.h postgresql-7.4.2-pgec/src/include/miscadmin.h --- postgresql-7.4.2/src/include/miscadmin.h 2003-09-24 14:54:01.000000000 -0400 +++ postgresql-7.4.2-pgec/src/include/miscadmin.h 2004-05-12 10:45:33.000000000 -0400 @@ -168,6 +168,9 @@ #define DATEORDER_DMY 1 #define DATEORDER_MDY 2 +/* Maximum number of tablespaces in config file */ +#define MAX_PG_TABLESPACES 32 + extern int DateStyle; extern int DateOrder; @@ -214,6 +217,8 @@ /* in utils/misc/database.c */ extern void GetRawDatabaseInfo(const char *name, Oid *db_id, char *path); extern char *ExpandDatabasePath(const char *path); +extern char *GetTablespacePath(const char *name); +extern void SetTablespace(const char *parameter); /* now in utils/init/miscinit.c */ extern void SetDatabasePath(const char *path); diff -u -r postgresql-7.4.2/src/include/utils/guc.h postgresql-7.4.2-pgec/src/include/utils/guc.h --- postgresql-7.4.2/src/include/utils/guc.h 2003-09-01 00:15:51.000000000 -0400 +++ postgresql-7.4.2-pgec/src/include/utils/guc.h 2004-04-09 10:03:54.000000000 -0400 @@ -114,6 +114,13 @@ extern int client_min_messages; extern int log_min_duration_statement; +/* Added MLW */ +extern char *runtime_pidfile; +extern char *explicit_pgconfig; +extern char *explicit_hbafile; +extern char *explicit_identfile; +extern bool explicit_isdir; +extern char *pgdatadir; extern void SetConfigOption(const char *name, const char *value, GucContext context, GucSource source); diff -u -r postgresql-7.4.2/src/include/utils/guc_tables.h postgresql-7.4.2-pgec/src/include/utils/guc_tables.h --- postgresql-7.4.2/src/include/utils/guc_tables.h 2003-08-03 22:40:15.000000000 -0400 +++ postgresql-7.4.2-pgec/src/include/utils/guc_tables.h 2004-04-09 10:03:54.000000000 -0400 @@ -61,7 +61,8 @@ PGC_BOOL, PGC_INT, PGC_REAL, - PGC_STRING + PGC_STRING, + PGC_FUNCTION }; /*