diff options
author | Sergey Poznyakoff <gray@gnu.org.ua> | 2009-09-30 17:50:15 +0300 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org.ua> | 2009-09-30 17:50:15 +0300 |
commit | a5466fa5a4c2ee60017bf9bbcb8d59a6627d8882 (patch) | |
tree | e0d9b9e1aaab239cbf72f1cb5829f2952f327fc9 | |
parent | 71b28b43f831d62fe3a5acdb61b5cfec23f39ac6 (diff) | |
download | mailfromd-a5466fa5a4c2ee60017bf9bbcb8d59a6627d8882.tar.gz mailfromd-a5466fa5a4c2ee60017bf9bbcb8d59a6627d8882.tar.bz2 |
Improve handling of deprecated features.
* mfd/deprecation.c: New file.
* mfd/Makefile.am (mailfromd_SOURCES): Add deprecation.c.
* mfd/mailfromd.h (vparse_warning): New proto.
(deprecation_warning, final_deprecation_warning)
(enable_deprecation_warnings, legacy_script_warning)
(open_change_conf, write_change_conf, write_db_config)
(close_change_conf): New functions.
* mfd/main.c: Move `change_conf' functions to deprecation.c.
* mfd/gram.y (parse_program): Emit final
deprecation warning if MAILFROMD_DEPRECATION is
set to no.
* mfd/lex.l: Use deprecation_warning for its
purpose.
(vparse_warning): New function.
-rw-r--r-- | mfd/Makefile.am | 1 | ||||
-rw-r--r-- | mfd/deprecation.c | 301 | ||||
-rw-r--r-- | mfd/gram.y | 1 | ||||
-rw-r--r-- | mfd/lex.l | 10 | ||||
-rw-r--r-- | mfd/mailfromd.h | 14 | ||||
-rw-r--r-- | mfd/main.c | 259 |
6 files changed, 330 insertions, 256 deletions
diff --git a/mfd/Makefile.am b/mfd/Makefile.am index d979158f..b197fa05 100644 --- a/mfd/Makefile.am +++ b/mfd/Makefile.am @@ -56,6 +56,7 @@ mailfromd_SOURCES = \ cache.c\ dnscache.c\ db.c\ + deprecation.c\ dns.c\ dnsbase.c\ engine.c\ diff --git a/mfd/deprecation.c b/mfd/deprecation.c new file mode 100644 index 00000000..40ab8256 --- /dev/null +++ b/mfd/deprecation.c @@ -0,0 +1,301 @@ +/* This file is part of Mailfromd. + Copyright (C) 2005, 2006, 2007, 2008, 2009 Sergey Poznyakoff + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "mailfromd.h" + +static int deprecated_features; + +int +enable_deprecation_warnings() +{ + static int retval = -1; + + if (retval == -1) { + char *p = getenv("MAILFROMD_DEPRECATION"); + if (!p) + retval = 1; + else if (strcmp(p, "no") == 0) + retval = 0; + } + return retval; +} + +void +deprecation_warning(const char *fmt, ...) +{ + if (enable_deprecation_warnings()) { + va_list ap; + + va_start(ap, fmt); + vparse_warning(fmt, ap); + va_end(ap); + } + deprecated_features = 1; +} + +void +final_deprecation_warning() +{ + if (deprecated_features && !enable_deprecation_warnings()) { + mu_diag_output(MU_DIAG_WARNING, + _("deprecated features used")); + mu_diag_output(MU_DIAG_WARNING, + _("unset environment variable MAILFROMD_DEPRECATION," + " or set it to `yes' to see detailed diagnostics")); + } +} + + +static FILE *change_conf_fp; +static size_t change_conf_deletes; +static int rename_legacy_file; + +extern enum mu_cfg_param_data_type config_statement_type(const char *name); + +int +open_change_conf() +{ + if (change_conf_fp) + return 0; + change_conf_fp = tmpfile(); + if (change_conf_fp == NULL) + return 1; + return 0; +} + +void +write_change_conf(const char *confkw, const char *value) +{ + enum mu_cfg_param_data_type type = config_statement_type (confkw); + const struct locus *loc = get_locus(); + + fprintf(change_conf_fp, + "D %lu %s\n", loc->line, loc->file); + fprintf(change_conf_fp, "C %s ", confkw); + switch (MU_CFG_TYPE(type)) { + case mu_cfg_string: + case mu_cfg_callback: + fprintf(change_conf_fp, "\"%s\"", value); + break; + + default: + fprintf(change_conf_fp, "%s", value); + } + fprintf(change_conf_fp, ";\n"); + change_conf_deletes++; +} + +void +write_db_config(const char *name, const char *stmt, const char *value) +{ + if (open_change_conf() == 0) { + const struct locus *loc = get_locus(); + + fprintf(change_conf_fp, + "D %lu %s\n", loc->line, loc->file); + fprintf(change_conf_fp, "G %s %s %s;\n", name, stmt, value); + change_conf_deletes++; + } +} + +static int +loc_cmp(const void *a, const void *b) +{ + const struct locus *la = a; + const struct locus *lb = b; + int rc = strcmp(la->file, lb->file); + + if (rc == 0) { + if (la->line > lb->line) + rc = -1; + else if (la->line < lb->line) + rc = 1; + } + return rc; +} + +struct db_statement { + struct db_statement *next; + char *name; + struct obstack obstack; +}; + +static struct db_statement * +find_db_statement(struct db_statement **phead, struct db_statement **ptail, + const char *name, size_t len) +{ + struct db_statement *p; + for (p = *phead; p; p = p->next) + if (strncmp(p->name, name, len) == 0) + return p; + + p = xmalloc(sizeof(*p)); + p->next = NULL; + p->name = xmalloc(len + 1); + memcpy(p->name, name, len); + p->name[len] = 0; + obstack_init(&p->obstack); + if (!*phead) + *phead = p; + else + (*ptail)->next = p; + *ptail = p; + return p; +} + +void +close_change_conf() +{ + size_t size = 0; + char *buf = NULL; + char *p; + const char *last_file; + size_t len; + struct locus *locus; + int i; + FILE *fp; + const char *script_name = rename_legacy_file ? + LEGACY_SCRIPT_FILE : DEFAULT_SCRIPT_FILE; + const char *file_name = "/tmp/mailfromd-newconf.sh"; + struct db_statement *dcg_head = NULL, *dcg_tail = NULL, *dcg; + time_t now = time(NULL); + + if (!change_conf_fp) + return; + + fp = fopen(file_name, "w"); + if (fp) { + mu_diag_output(MU_DIAG_INFO, + _("run script %s to fix the above warnings"), + file_name); + } else + fp = stdout; + locus = xcalloc(change_conf_deletes, sizeof(locus[0])); + fseek(change_conf_fp, 0, SEEK_SET); + + fprintf(fp, "#! /bin/sh\n"); + fprintf(fp, "# Conversion script created by mailfromd on %s", + ctime (&now)); + fprintf(fp, "# Run this script to fix mailfromd deprecation warnings\n\n"); + fprintf(fp, + "set -e\n" + "if test -r " DEFAULT_CONFIG_FILE " ; then\n" + " echo >&2 \"$0: " DEFAULT_CONFIG_FILE " already exists\"\n" + " exit 1\n" + "fi\n" + "if ! test -r %s ; then\n" + " echo >&2 \"$0: %s does not exist\"\n" + " exit 1\n" + "fi\n" + "if test %s -nt $0; then\n" + " echo >&2 \"$0: %s is updated, re-run mailfromd --lint\"\n" + " exit 1\n" + "fi\n", + script_name, + script_name, + script_name, + script_name); + fprintf(fp, "# 1. Create new configuration file\n"); + fprintf(fp, "cat > %s <<'EOT'\n", DEFAULT_CONFIG_FILE); + i = 0; + while (getline(&buf, &size, change_conf_fp) > 0) { + switch (buf[0]) { + case 'D': + locus[i].line = strtoul(buf+1, &p, 0); + p++; + len = strlen(p); + p[len-1] = 0; + locus[i].file = xstrdup(p); + i++; + break; + + case 'G': + p = strchr (buf+2, ' '); + dcg = find_db_statement(&dcg_head, &dcg_tail, + buf + 2, p - buf - 2); + obstack_grow (&dcg->obstack, " ", 2); + obstack_grow (&dcg->obstack, p + 1, strlen (p + 1)); + break; + + case 'C': + fprintf(fp, "%s", buf+2); + } + } + + + for (dcg = dcg_head; dcg;) { + struct db_statement *next = dcg->next; + + fprintf(fp, "database %s {\n", dcg->name); + obstack_1grow (&dcg->obstack, 0); + p = obstack_finish(&dcg->obstack); + fprintf(fp, "%s", p); + fprintf(fp, "}\n"); + obstack_free(&dcg->obstack, NULL); + free(dcg->name); + free(dcg); + dcg = next; + } + fprintf(fp, "EOT\n"); + fclose(change_conf_fp); + free(buf); + + fprintf(fp, "#\n# 2. Fix existing script file(s)\n"); + qsort(locus, change_conf_deletes, sizeof(locus[0]), loc_cmp); + + last_file = NULL; + for (i = 0; i < change_conf_deletes; i++) { + if (last_file == NULL || strcmp(locus[i].file, last_file)) { + if (last_file) + fprintf(fp, "' %s.tmp > %s\n", + last_file, last_file); + last_file = locus[i].file; + fprintf(fp, "mv %s %s.tmp\n", + last_file, last_file); + fprintf(fp, "sed '"); + } + fprintf(fp, "%lud;", locus[i].line); + } + fprintf(fp, "' %s.tmp > %s\n", last_file, last_file); + if (rename_legacy_file) { + fprintf(fp, "#\n# 3. Rename script file\n"); + fprintf(fp, "mv %s %s\n", + LEGACY_SCRIPT_FILE, DEFAULT_SCRIPT_FILE); + } + fprintf(fp, "# EOF\n"); + fclose(fp); + + for (i = 0; i < change_conf_deletes; i++) + free((char*)locus[i].file); + free(locus); +} + +void +legacy_script_warning() +{ + mu_diag_output(MU_DIAG_WARNING, + _("using legacy script file %s"), + LEGACY_SCRIPT_FILE); + mu_diag_output(MU_DIAG_WARNING, + _("rename it to %s or use script-file statement in %s to disable this warning"), + DEFAULT_SCRIPT_FILE, + DEFAULT_CONFIG_FILE); + rename_legacy_file = 1; +} @@ -2257,6 +2257,7 @@ parse_program(char *name, int ydebug) catch_nesting = 0; code_immediate(NULL); /* Reserve 0 slot */ rc = yyparse() + error_count; + final_deprecation_warning(); return rc; } @@ -319,7 +319,7 @@ ICONST {LOCUS}|{VCONST}|{STATEDIR}|{PREPROC} parse_include(yytext, 0); } ^[ \t]*#[ \t]*require[ \t].*\n { - parse_warning(_("#require is deprecated, use `require' or `from ... import' instead")); + deprecation_warning(_("#require is deprecated, use `require' or `from ... import' instead")); /* parse_require cannot be called directly from lexer to avoid switching module context in the middle of grammar rule. */ yylval.string = yytext; @@ -815,6 +815,12 @@ print_parse_message(const struct locus *locus, } void +vparse_warning(const char *fmt, va_list ap) +{ + print_parse_message(&locus, _("warning"), fmt, ap); +} + +void parse_warning(const char *fmt, ...) { va_list ap; @@ -856,6 +862,8 @@ parse_error_locus(const struct locus *loc, const char *fmt, ...) error_count++; } + + static int lex_close_source() { diff --git a/mfd/mailfromd.h b/mfd/mailfromd.h index 13273b2a..8ea0fbe7 100644 --- a/mfd/mailfromd.h +++ b/mfd/mailfromd.h @@ -808,6 +808,8 @@ void parse_error_locus(const struct locus *loc, const char *fmt, ...) void parse_warning(const char *fmt, ...) MU_PRINTFLIKE(1,2); void parse_warning_locus(const struct locus *loc, const char *fmt, ...) MU_PRINTFLIKE(2,3); +void vparse_warning(const char *fmt, va_list ap); + void print_syntax_tree(void); void print_macros(void); const char *function_name(void); @@ -935,8 +937,6 @@ void pp_define(const char *symbol); void mailfromd_test(int argc, char **argv); void mailfromd_run(prog_counter_t entry, int argc, char **argv); -void write_db_config(const char *name, const char *stmt, const char *value); - int set_option(char *name, char *value, int override, int pragma); void milter_enable_state(enum smtp_state state); int xeval(eval_environ_t env, enum smtp_state tag); @@ -1036,3 +1036,13 @@ int mfd_app_init (struct argp *myargp, const char **capa, struct mu_cfg_param *cfg_param, int argc, char **argv, int flags, int *pindex, void *data); + +/* deprecation.c */ +void deprecation_warning(const char *fmt, ...) MU_PRINTFLIKE(1,2); +void final_deprecation_warning(void); +int enable_deprecation_warnings(void); +void legacy_script_warning(void); +int open_change_conf(void); +void write_change_conf(const char *confkw, const char *value); +void write_db_config(const char *name, const char *stmt, const char *value); +void close_change_conf(void); @@ -500,231 +500,6 @@ mf_option_source_ip(mu_debug_t err, const char *arg, unsigned long *pval) } -FILE *change_conf_fp; -size_t change_conf_deletes; -int rename_legacy_file; - -static enum mu_cfg_param_data_type config_statement_type(const char *name); - -int -open_change_conf() -{ - if (change_conf_fp) - return 0; - change_conf_fp = tmpfile(); - if (change_conf_fp == NULL) - return 1; - return 0; -} - -void -write_change_conf(const char *confkw, const char *value) -{ - enum mu_cfg_param_data_type type = config_statement_type (confkw); - const struct locus *loc = get_locus(); - - fprintf(change_conf_fp, - "D %lu %s\n", loc->line, loc->file); - fprintf(change_conf_fp, "C %s ", confkw); - switch (MU_CFG_TYPE(type)) { - case mu_cfg_string: - case mu_cfg_callback: - fprintf(change_conf_fp, "\"%s\"", value); - break; - - default: - fprintf(change_conf_fp, "%s", value); - } - fprintf(change_conf_fp, ";\n"); - change_conf_deletes++; -} - -void -write_db_config(const char *name, const char *stmt, const char *value) -{ - if (open_change_conf() == 0) { - const struct locus *loc = get_locus(); - - fprintf(change_conf_fp, - "D %lu %s\n", loc->line, loc->file); - fprintf(change_conf_fp, "G %s %s %s;\n", name, stmt, value); - change_conf_deletes++; - } -} - -static int -loc_cmp(const void *a, const void *b) -{ - const struct locus *la = a; - const struct locus *lb = b; - int rc = strcmp(la->file, lb->file); - - if (rc == 0) { - if (la->line > lb->line) - rc = -1; - else if (la->line < lb->line) - rc = 1; - } - return rc; -} - -struct db_statement { - struct db_statement *next; - char *name; - struct obstack obstack; -}; - -struct db_statement * -find_db_statement(struct db_statement **phead, struct db_statement **ptail, - const char *name, size_t len) -{ - struct db_statement *p; - for (p = *phead; p; p = p->next) - if (strncmp(p->name, name, len) == 0) - return p; - - p = xmalloc(sizeof(*p)); - p->next = NULL; - p->name = xmalloc(len + 1); - memcpy(p->name, name, len); - p->name[len] = 0; - obstack_init(&p->obstack); - if (!*phead) - *phead = p; - else - (*ptail)->next = p; - *ptail = p; - return p; -} - - -void -close_change_conf() -{ - size_t size = 0; - char *buf = NULL; - char *p; - const char *last_file; - size_t len; - struct locus *locus; - int i; - FILE *fp; - const char *script_name = rename_legacy_file ? - LEGACY_SCRIPT_FILE : DEFAULT_SCRIPT_FILE; - const char *file_name = "/tmp/mailfromd-newconf.sh"; - struct db_statement *dcg_head = NULL, *dcg_tail = NULL, *dcg; - time_t now = time(NULL); - - if (!change_conf_fp) - return; - - fp = fopen(file_name, "w"); - if (fp) { - mu_diag_output(MU_DIAG_INFO, - _("run script %s to fix the above warnings"), - file_name); - } else - fp = stdout; - locus = xcalloc(change_conf_deletes, sizeof(locus[0])); - fseek(change_conf_fp, 0, SEEK_SET); - - fprintf(fp, "#! /bin/sh\n"); - fprintf(fp, "# Conversion script created by mailfromd on %s", - ctime (&now)); - fprintf(fp, "# Run this script to fix mailfromd deprecation warnings\n\n"); - fprintf(fp, - "set -e\n" - "if test -r " DEFAULT_CONFIG_FILE " ; then\n" - " echo >&2 \"$0: " DEFAULT_CONFIG_FILE " already exists\"\n" - " exit 1\n" - "fi\n" - "if ! test -r %s ; then\n" - " echo >&2 \"$0: %s does not exist\"\n" - " exit 1\n" - "fi\n" - "if test %s -nt $0; then\n" - " echo >&2 \"$0: %s is updated, re-run mailfromd --lint\"\n" - " exit 1\n" - "fi\n", - script_name, - script_name, - script_name, - script_name); - fprintf(fp, "# 1. Create new configuration file\n"); - fprintf(fp, "cat > %s <<'EOT'\n", DEFAULT_CONFIG_FILE); - i = 0; - while (getline(&buf, &size, change_conf_fp) > 0) { - switch (buf[0]) { - case 'D': - locus[i].line = strtoul(buf+1, &p, 0); - p++; - len = strlen(p); - p[len-1] = 0; - locus[i].file = xstrdup(p); - i++; - break; - - case 'G': - p = strchr (buf+2, ' '); - dcg = find_db_statement(&dcg_head, &dcg_tail, - buf + 2, p - buf - 2); - obstack_grow (&dcg->obstack, " ", 2); - obstack_grow (&dcg->obstack, p + 1, strlen (p + 1)); - break; - - case 'C': - fprintf(fp, "%s", buf+2); - } - } - - - for (dcg = dcg_head; dcg;) { - struct db_statement *next = dcg->next; - - fprintf(fp, "database %s {\n", dcg->name); - obstack_1grow (&dcg->obstack, 0); - p = obstack_finish(&dcg->obstack); - fprintf(fp, "%s", p); - fprintf(fp, "}\n"); - obstack_free(&dcg->obstack, NULL); - free(dcg->name); - free(dcg); - dcg = next; - } - fprintf(fp, "EOT\n"); - fclose(change_conf_fp); - free(buf); - - fprintf(fp, "#\n# 2. Fix existing script file(s)\n"); - qsort(locus, change_conf_deletes, sizeof(locus[0]), loc_cmp); - - last_file = NULL; - for (i = 0; i < change_conf_deletes; i++) { - if (last_file == NULL || strcmp(locus[i].file, last_file)) { - if (last_file) - fprintf(fp, "' %s.tmp > %s\n", - last_file, last_file); - last_file = locus[i].file; - fprintf(fp, "mv %s %s.tmp\n", - last_file, last_file); - fprintf(fp, "sed '"); - } - fprintf(fp, "%lud;", locus[i].line); - } - fprintf(fp, "' %s.tmp > %s\n", last_file, last_file); - if (rename_legacy_file) { - fprintf(fp, "#\n# 3. Rename script file\n"); - fprintf(fp, "mv %s %s\n", - LEGACY_SCRIPT_FILE, DEFAULT_SCRIPT_FILE); - } - fprintf(fp, "# EOF\n"); - fclose(fp); - - for (i = 0; i < change_conf_deletes; i++) - free((char*)locus[i].file); - free(locus); -} - void conf_cache_positive_expire_interval (const char *kw, const char *text) { @@ -1098,21 +873,6 @@ find_option(char *name) return NULL; } -static int -enable_pragma_deprecation_warning() -{ - static int retval = -1; - - if (retval == -1) { - char *p = getenv("MAILFROMD_DEPRECATION"); - if (!p) - retval = 1; - else if (strcmp(p, "no") == 0) - retval = 0; - } - return retval; -} - int set_option(char *name, char *value, int override, int pragma) { @@ -1121,10 +881,10 @@ set_option(char *name, char *value, int override, int pragma) errno = ENOENT; return 1; } - if (pragma && enable_pragma_deprecation_warning()) { - parse_warning(_("this pragma is deprecated: " - "use %s configuration statement instead"), - p->confkw); + if (pragma && enable_deprecation_warnings()) { + deprecation_warning(_("this pragma is deprecated: " + "use %s configuration statement instead"), + p->confkw); if (open_change_conf() == 0) { if (p->conffn) p->conffn(p->confkw, value); @@ -2276,7 +2036,7 @@ struct mu_cfg_param mf_cfg_param[] = { { NULL } }; -static enum mu_cfg_param_data_type +enum mu_cfg_param_data_type config_statement_type(const char *name) { struct mu_cfg_param *p; @@ -2687,15 +2447,8 @@ main(int argc, char **argv) else if (access(script_file, R_OK) && errno == ENOENT && access (LEGACY_SCRIPT_FILE, R_OK) == 0) { - mu_diag_output(MU_DIAG_WARNING, - _("using legacy script file %s"), - LEGACY_SCRIPT_FILE); - mu_diag_output(MU_DIAG_WARNING, - _("rename it to %s or use script-file statement in %s to disable this warning"), - DEFAULT_SCRIPT_FILE, - DEFAULT_CONFIG_FILE); + legacy_script_warning(); script_file = LEGACY_SCRIPT_FILE; - rename_legacy_file = 1; } if (script_file[0] != '/') |