aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2009-09-30 17:50:15 +0300
committerSergey Poznyakoff <gray@gnu.org.ua>2009-09-30 17:50:15 +0300
commita5466fa5a4c2ee60017bf9bbcb8d59a6627d8882 (patch)
treee0d9b9e1aaab239cbf72f1cb5829f2952f327fc9
parent71b28b43f831d62fe3a5acdb61b5cfec23f39ac6 (diff)
downloadmailfromd-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.am1
-rw-r--r--mfd/deprecation.c301
-rw-r--r--mfd/gram.y1
-rw-r--r--mfd/lex.l10
-rw-r--r--mfd/mailfromd.h14
-rw-r--r--mfd/main.c259
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;
+}
diff --git a/mfd/gram.y b/mfd/gram.y
index 4080fa7c..bc6f7fe7 100644
--- a/mfd/gram.y
+++ b/mfd/gram.y
@@ -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;
}
diff --git a/mfd/lex.l b/mfd/lex.l
index 4ccf7a0a..83aa1947 100644
--- a/mfd/lex.l
+++ b/mfd/lex.l
@@ -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);
diff --git a/mfd/main.c b/mfd/main.c
index 9a392ea1..b76b3e28 100644
--- a/mfd/main.c
+++ b/mfd/main.c
@@ -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] != '/')

Return to:

Send suggestions and report system problems to the System administrator.