diff --git a/src/backend/utils/misc/guc-file.l b/src/backend/utils/misc/guc-file.l index 8fe676671e603722985b731ffe32f0078d406352..86f50359997b11a6a8a3b9973dacf8155bcfc2d2 100644 --- a/src/backend/utils/misc/guc-file.l +++ b/src/backend/utils/misc/guc-file.l @@ -4,7 +4,7 @@ * * Copyright (c) 2000-2004, PostgreSQL Global Development Group * - * $PostgreSQL: pgsql/src/backend/utils/misc/guc-file.l,v 1.24 2004/08/29 04:13:00 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/utils/misc/guc-file.l,v 1.25 2004/08/31 22:43:58 tgl Exp $ */ %{ @@ -13,7 +13,6 @@ #include <sys/stat.h> #include <unistd.h> -#include <errno.h> #include <ctype.h> #include "miscadmin.h" @@ -39,11 +38,9 @@ enum { GUC_ERROR = 100 }; -#define YY_USER_INIT (ConfigFileLineno = 1) - /* prototype, so compiler is happy with our high warnings setting */ int GUC_yylex(void); -char *GUC_scanstr(char *); +static char *GUC_scanstr(char *); %} %option 8bit @@ -98,7 +95,6 @@ struct name_value_pair }; - /* * Free a list of name/value pairs, including the names and the values */ @@ -113,9 +109,9 @@ free_name_value_list(struct name_value_pair * list) struct name_value_pair *save; save = item->next; - free(item->name); - free(item->value); - free(item); + pfree(item->name); + pfree(item->value); + pfree(item); item = save; } } @@ -123,30 +119,74 @@ free_name_value_list(struct name_value_pair * list) /* * 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. + * parameter indicates in what context the file is being read --- either + * postmaster startup (including standalone-backend startup) or SIGHUP. + * All options mentioned in the configuration file are set to new values. + * If an error occurs, no values will be changed. */ -static void -ReadConfigFile(char *filename, GucContext context) +void +ProcessConfigFile(GucContext context) { - int token, parse_state; - char *opt_name, *opt_value; + int elevel; + char *filename; + int token, parse_state; + char *opt_name, *opt_value; struct name_value_pair *item, *head, *tail; - int elevel; - FILE * fp; + FILE *fp; + + Assert(context == PGC_POSTMASTER || context == PGC_SIGHUP); + + if (context == PGC_SIGHUP) + { + /* + * To avoid cluttering the log, only the postmaster bleats loudly + * about problems with the config file. + */ + elevel = IsUnderPostmaster ? DEBUG2 : LOG; + } + else + elevel = ERROR; + + /* + * Handle the various possibilities for config file location + */ + if (user_pgconfig) + { + struct stat sb; - elevel = (context == PGC_SIGHUP) ? DEBUG4 : ERROR; + if (stat(user_pgconfig, &sb) != 0) + { + ereport(elevel, + (errcode_for_file_access(), + errmsg("could not access configuration file \"%s\": %m", + user_pgconfig))); + return; + } + + if (S_ISDIR(sb.st_mode)) + { + filename = palloc(strlen(user_pgconfig) + strlen(CONFIG_FILENAME) + 2); + sprintf(filename, "%s/%s", user_pgconfig, CONFIG_FILENAME); + user_pgconfig_is_dir = true; + } + else + filename = pstrdup(user_pgconfig); /* Use explicit file */ + } + else + { + /* Find config in datadir */ + filename = palloc(strlen(DataDir) + strlen(CONFIG_FILENAME) + 2); + sprintf(filename, "%s/%s", DataDir, CONFIG_FILENAME); + } fp = AllocateFile(filename, "r"); if (!fp) { - free(filename); ereport(elevel, - (errcode_for_file_access(), - errmsg("could not open configuration file \"%s\": %m", filename))); + (errcode_for_file_access(), + errmsg("could not open configuration file \"%s\": %m", + filename))); + pfree(filename); return; } @@ -157,8 +197,10 @@ ReadConfigFile(char *filename, GucContext context) parse_state = 0; head = tail = NULL; opt_name = opt_value = NULL; + ConfigFileLineno = 1; while ((token = yylex())) + { switch(parse_state) { case 0: /* no previous input */ @@ -166,9 +208,7 @@ ReadConfigFile(char *filename, GucContext context) continue; if (token != GUC_ID && token != GUC_QUALIFIED_ID) goto parse_error; - opt_name = strdup(yytext); - if (opt_name == NULL) - goto out_of_memory; + opt_name = pstrdup(yytext); parse_state = 1; break; @@ -182,18 +222,16 @@ ReadConfigFile(char *filename, GucContext context) token != GUC_REAL && token != GUC_UNQUOTED_STRING) goto parse_error; - opt_value = strdup(yytext); - if (opt_value == NULL) - goto out_of_memory; + opt_value = pstrdup(yytext); if (token == GUC_STRING) { /* remove the beginning and ending quote/apostrophe */ /* first: shift the whole thing down one character */ - memmove(opt_value,opt_value+1,strlen(opt_value)-1); + memmove(opt_value, opt_value+1, strlen(opt_value)-1); /* second: null out the 2 characters we shifted */ - opt_value[strlen(opt_value)-2]='\0'; - /* do the escape thing. free()'s the strdup above */ - opt_value=GUC_scanstr(opt_value); + opt_value[strlen(opt_value)-2] = '\0'; + /* do the escape thing. pfree()'s the pstrdup above */ + opt_value = GUC_scanstr(opt_value); } parse_state = 2; break; @@ -202,45 +240,40 @@ ReadConfigFile(char *filename, GucContext context) if (token != GUC_EOL) goto parse_error; + item = palloc(sizeof *item); + item->name = opt_name; + item->value = opt_value; + if (strcmp(opt_name, "custom_variable_classes") == 0) { - /* This variable must be added first as it controls the validity - * of other variables + /* + * This variable must be processed first as it controls + * the validity of other variables; so prepend to + * the list instead of appending. */ - if (!set_config_option(opt_name, opt_value, context, - PGC_S_FILE, false, true)) - { - FreeFile(fp); - free(filename); - goto cleanup_exit; - } - - /* Don't include in list */ - parse_state = 0; - break; + item->next = head; + head = item; + if (!tail) + tail = item; } - - /* append to list */ - item = malloc(sizeof *item); - if (item == NULL) - goto out_of_memory; - item->name = opt_name; - item->value = opt_value; - item->next = NULL; - - if (!head) - tail = head = item; else { - tail->next = item; + /* append to list */ + item->next = NULL; + if (!head) + head = item; + else + tail->next = item; tail = item; } parse_state = 0; break; } + } FreeFile(fp); + pfree(filename); /* * Check if all options are valid @@ -252,10 +285,12 @@ ReadConfigFile(char *filename, GucContext context) goto cleanup_exit; } - /* If we got here all the options parsed okay. */ + /* If we got here all the options parsed okay, so apply them. */ for(item = head; item; item=item->next) + { set_config_option(item->name, item->value, context, PGC_S_FILE, false, true); + } cleanup_exit: free_name_value_list(head); @@ -264,79 +299,17 @@ ReadConfigFile(char *filename, GucContext context) parse_error: FreeFile(fp); free_name_value_list(head); - ereport(elevel, - (errcode(ERRCODE_SYNTAX_ERROR), - errmsg("syntax error in file \"%s\" line %u, near token \"%s\"", - filename, ConfigFileLineno, yytext))); - return; - - out_of_memory: - FreeFile(fp); - free(filename); - free_name_value_list(head); - ereport(elevel, - (errcode(ERRCODE_OUT_OF_MEMORY), - errmsg("out of memory"))); - return; -} - -/* - * Function to read and process the configuration file. The - * parameter indicates the context that 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 (user_pgconfig) - { - struct stat sb; - - if (stat(user_pgconfig, &sb) != 0) - { - int elevel = (context == PGC_SIGHUP) ? DEBUG3 : ERROR; - elog(elevel, "Configuration file \"%s\" does not exist", user_pgconfig); - return; - } - - if (S_ISDIR(sb.st_mode)) - { - /* This will cause a small one time memory leak - * if the user also specifies hba_conf, - * ident_conf, and data_dir - */ - filename = malloc(strlen(user_pgconfig) + strlen(CONFIG_FILENAME) + 2); - sprintf(filename, "%s/%s", user_pgconfig, CONFIG_FILENAME); - user_pgconfig_is_dir = true; - } - else - filename = strdup(user_pgconfig); /* Use explicit file */ - } + if (token == GUC_EOL) + ereport(elevel, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("syntax error in file \"%s\" line %u, near end of line", + filename, ConfigFileLineno - 1))); else - { - /* Use datadir for 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; - } - - ReadConfigFile(filename, context); - - free(filename); + ereport(elevel, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("syntax error in file \"%s\" line %u, near token \"%s\"", + filename, ConfigFileLineno, yytext))); + pfree(filename); } @@ -347,12 +320,12 @@ ProcessConfigFile(GucContext context) * if the string passed in has escaped codes, map the escape codes to actual * chars * - * the string returned is malloc'd and should eventually be free'd by the - * caller! + * the string returned is palloc'd and should eventually be pfree'd by the + * caller; also we assume we should pfree the input string. * ---------------- */ -char * +static char * GUC_scanstr(char *s) { char *newStr; @@ -363,16 +336,12 @@ GUC_scanstr(char *s) if (s == NULL || s[0] == '\0') { if (s != NULL) - free(s); - return strdup(""); + pfree(s); + return pstrdup(""); } len = strlen(s); - newStr = malloc(len + 1); /* string cannot get longer */ - if (newStr == NULL) - ereport(FATAL, - (errcode(ERRCODE_OUT_OF_MEMORY), - errmsg("out of memory"))); + newStr = palloc(len + 1); /* string cannot get longer */ for (i = 0, j = 0; i < len; i++) { @@ -426,6 +395,6 @@ GUC_scanstr(char *s) j++; } newStr[j] = '\0'; - free(s); + pfree(s); return newStr; } diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c index b3b6ce0470d4a258e1da22381e1d1abcb8a490af..436c57b750f4b192302c2ba01e5b0b9e1480c1bd 100644 --- a/src/backend/utils/misc/guc.c +++ b/src/backend/utils/misc/guc.c @@ -10,7 +10,7 @@ * Written by Peter Eisentraut <peter_e@gmx.net>. * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/utils/misc/guc.c,v 1.237 2004/08/31 19:28:51 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/utils/misc/guc.c,v 1.238 2004/08/31 22:43:58 tgl Exp $ * *-------------------------------------------------------------------- */ @@ -116,7 +116,6 @@ static bool assign_log_stats(bool newval, bool doit, GucSource source); static bool assign_transaction_read_only(bool newval, bool doit, GucSource source); static const char *assign_canonical_path(const char *newval, bool doit, GucSource source); -static void ReadConfigFile(char *filename, GucContext context); /* * Debugging options @@ -3079,7 +3078,13 @@ set_config_option(const char *name, const char *value, changeValOrig = changeVal; if (context == PGC_SIGHUP || source == PGC_S_DEFAULT) - elevel = DEBUG2; + { + /* + * To avoid cluttering the log, only the postmaster bleats loudly + * about problems with the config file. + */ + elevel = IsUnderPostmaster ? DEBUG2 : LOG; + } else if (source == PGC_S_DATABASE || source == PGC_S_USER) elevel = INFO; else @@ -4715,7 +4720,8 @@ write_nondefault_variables(GucContext context) Assert(context == PGC_POSTMASTER || context == PGC_SIGHUP); Assert(DataDir); - elevel = (context == PGC_SIGHUP) ? DEBUG4 : ERROR; + + elevel = (context == PGC_SIGHUP) ? LOG : ERROR; /* * Open file