aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2009-05-31 20:11:19 +0300
committerSergey Poznyakoff <gray@gnu.org.ua>2009-05-31 20:11:45 +0300
commitfa0978a70e893bbc73d4c4816699cf241eefd3c5 (patch)
treed4c6b100c75d50f21cfdbfcb5e21da02874fcb4f
parentb7fb81d841a26476da18349200dccce86c2de337 (diff)
downloadmailfromd-fa0978a70e893bbc73d4c4816699cf241eefd3c5.tar.gz
mailfromd-fa0978a70e893bbc73d4c4816699cf241eefd3c5.tar.bz2
Implement `localdomain' function + several improvements.
* NEWS: Update. * etc/mailfromd.rc: Use localdomain to determine the domain name. Remove the `#error' statement. Hopefully, this file can be used as is. * mfd/bi_gethostname.m4 (gethostname): Add an optional argument. * mfd/gram.y: Handle function declarations with only optional arguments, e.g.: func foo(; string bar) (mailfromd_test): Add missing env_init calls. * mfd/lex.l: Remove trailing newline before displaying the `#error' diagnostics. * mflib/localdomain.mf: New file. * mflib/Makefile.am (inc_DATA): Add localdomain.mf. * mflib/safedb.mf4 (safedb_verbose): New variable. (safedbmap, safedbdel): New function. (safedbget, safedbput): Verbosely print exceptions caught if safedb_verbose is set.
-rw-r--r--NEWS33
-rw-r--r--doc/mailfromd.texi117
-rw-r--r--etc/mailfromd.rc17
-rw-r--r--mfd/bi_gethostname.m417
-rw-r--r--mfd/gram.y21
-rw-r--r--mfd/lex.l5
-rw-r--r--mflib/Makefile.am1
-rw-r--r--mflib/localdomain.mf31
-rw-r--r--mflib/safedb.mf448
9 files changed, 240 insertions, 50 deletions
diff --git a/NEWS b/NEWS
index 2309eb87..18c168e3 100644
--- a/NEWS
+++ b/NEWS
@@ -1,4 +1,4 @@
-Mailfromd NEWS -- history of user-visible changes. 2009-05-23
+Mailfromd NEWS -- history of user-visible changes. 2009-05-31
Copyright (C) 2005, 2006, 2007, 2008, 2009 Sergey Poznyakoff
See the end of file for copying conditions.
@@ -37,6 +37,37 @@ m4_ifdef(`WITH_GEOIP',`
add "X-Originator-Country" geoip_country_code_by_addr($client_addr)
')
+* The gethostname function
+
+The gethostname function takes an optional argument:
+
+ string gethostname ([bool FQN])
+
+If FQN is specified and is `true', the function attempts to determine
+a fully qualified host name.
+
+* The localdomain function
+
+New function is defined in the library module `localdomain':
+
+ string localdomain()
+
+It returns the domain name of the box mailfromd is executed on.
+It is more reliable than getdomainname, because it uses DNS to
+determine the fully qualified domain name.
+
+* `Safedb' functions.
+
+Two new `safedb' interfaces are implemented:
+
+ string safedbmap (string db, string key [, string defval, number null])
+ void safedbdel (string db, string key [, number null])
+
+A new global variable is added, which controls the verbosity of all
+safedb functions. If the variable safedb_verbose is set to 1, these
+functions log the detailed diagnostics about intercepted exceptions
+before returning to the caller.
+
* Debugging
New function mailutils_set_debug_level allows to set global Mailutils
diff --git a/doc/mailfromd.texi b/doc/mailfromd.texi
index 4bbbea9b..62b41a06 100644
--- a/doc/mailfromd.texi
+++ b/doc/mailfromd.texi
@@ -5249,6 +5249,11 @@ Spam threshold, set by @code{sa} function (@pxref{sa}).
Spam keywords for the message, set by @code{sa} function (@pxref{sa}).
@end deftypevr
+@deftypevr {Predefined Variable} number safedb_verbose
+This variable controls the verbosity of the exception-safe database
+functions. @xref{safedb_verbose}.
+@end deftypevr
+
@node Back references
@section Back references
@@ -7556,24 +7561,6 @@ specified, or empty string otherwise.
See above for the meaning of @var{null}.
@end deftypefn
-@deftypefn {Library Function} string safedbget (string @var{db}, @
- string @var{key} [, string @var{default}, number @var{null}])
-
- This is an exception-safe interface to @code{dbget}. If some
-database error occurs while attempting to retrieve the record,
-@code{safedbget} returns empty string.
-
-@flindex safedb.mf
- To use this function, request the @file{safedb.mf} module:
-
-@smallexample
-#require safedb
-@end smallexample
-
-@noindent
-@xref{Modules}, for a description of @acronym{MFL} module system.
-@end deftypefn
-
@deftypefn {Built-in Function} void dbput (string @var{db}, @
string @var{key}, string @var{value} [, @
number @var{null}, number @var{mode} ])
@@ -7586,37 +7573,72 @@ to explicitly specify the file mode for this database. See also
@code{#pragma dbprop}, described above.
@end deftypefn
-@deftypefn {Library Function} void safedbput (string @var{db}, @
- string @var{key}, string @var{value} [, number @var{null}])
- This is an exception-safe interface to @code{dbput}. If a
-database error occurs while attempting to retrieve the record,
-the function returns without reporting an error.
+@deftypefn {Built-in Function} void dbdel (string @var{db}, @
+ string @var{key} [, number @var{null}, number @var{mode}])
+ Delete from the database the record with the given @var{key}. If
+there are no such record, return without signalling error.
+
+ If the optional @var{null} argument is given and is not zero, the
+terminating null character will be included in @var{key} length.
+
+ Optional @var{mode} allows to explicitly specify the file mode for
+this database. See also @code{#pragma dbprop}, described above.
+@end deftypefn
@flindex safedb.mf
- To use this function, request the @file{safedb.mf} module:
+The functions above have also the corresponding exception-safe
+interfaces, which return cleanly if the @samp{e_dbfailure} exception
+occurs. To use these interfaces, request the @file{safedb.mf} module:
@smallexample
#require safedb
@end smallexample
-@noindent
-@xref{Modules}, for a description of @acronym{MFL} module system.
-@FIXME{safedbput should probably take an optional mode argument, as
-dbput does.}
+The exception-safe interfaces are:
+
+@deftypefn {Library Function} string safedbmap (string @var{db}, @
+ string @var{key} [, string @var{default}, number @var{null}])
+
+ This is an exception-safe interface to @code{dbmap}. If a
+database error occurs while attempting to retrieve the record,
+@code{safedbmap} returns @var{default} or @samp{0}, if it is
+not defined.
@end deftypefn
-@deftypefn {Built-in Function} void dbdel (string @var{db}, @
- string @var{key} [, number @var{null}, number @var{mode}])
- Delete from the database the record with the given @var{key}. If
-there are no such record, return without signalling error.
+@deftypefn {Library Function} string safedbget (string @var{db}, @
+ string @var{key} [, string @var{default}, number @var{null}])
- If the optional @var{null} argument is given and is not zero, the
-terminating null character will be included in @var{key} length.
+ This is an exception-safe interface to @code{dbget}. If a
+database error occurs while attempting to retrieve the record,
+@code{safedbget} returns @var{default} or empty string, if it is
+not defined.
+@end deftypefn
- Optional @var{mode} allows to explicitly specify the file mode for
-this database. See also @code{#pragma dbprop}, described above.
+@deftypefn {Library Function} void safedbput (string @var{db}, @
+ string @var{key}, string @var{value} [, number @var{null}])
+
+ This is an exception-safe interface to @code{dbput}. If a
+database error occurs while attempting to retrieve the record,
+the function returns without raising exception.
@end deftypefn
+@deftypefn {Library Function} void safedbdel (string @var{db}, @
+ string @var{key} [, number @var{null}])
+
+ This is an exception-safe interface to @code{dbdel}. If a
+database error occurs while attempting to delete the record,
+the function returns without raising exception.
+@end deftypefn
+
+@anchor{safedb_verbose}
+@vrindex safedb_verbose
+The verbosity of @samp{safedb} interfaces in case of database error is
+controlled by the value of @code{safedb_verbose} variable. If it is
+@samp{0}, these functions return silently. This is the default
+behavior. Otherwise, if @code{safedb_verbose} is not @samp{0}, these
+functions log the detailed diagnostics about the database error and
+return.
+
@anchor{dbm-seq}
The following functions provide a sequential access to the contents of
a @acronym{DBM} database:
@@ -7820,8 +7842,12 @@ The function @code{revip} is defined in @ref{revip}.
@node System functions
@subsubsection System functions
-@deftypefn {Built-in Function} string gethostname ()
+@deftypefn {Built-in Function} string gethostname ([bool @var{fqn}])
Return the host name of this machine.
+
+If the optional @var{fqn} is given and is @samp{true}, the function
+will attempt to return fully-qualified host name, by attempting to
+resolve it using @acronym{DNS}.
@end deftypefn
@deftypefn {Built-in Function} string getdomainname ()
@@ -7830,8 +7856,21 @@ necessarily coincide with the actual machine name in @acronym{DNS}.
Depending on the underlying @samp{libc} implementation, this call may
return empty string or the string @samp{(none)}. Do not rely on it to
-get the real hostname of the box @command{mailfromd} runs on, use
-@acronym{DNS} functions instead.
+get the real domain name of the box @command{mailfromd} runs on, use
+@code{localdomain} (see below) instead.
+@end deftypefn
+
+@flindex localdomain.mf
+@deftypefn {Library Function} string localdomain ()
+Return the local domain name of this machine.
+
+This function first uses @code{getdomainname} to make a first guess.
+If it does not return a meaningful value, @code{localdomain} calls
+@code{gethostname(1)} to determine the fully qualified host name of
+the machine, and returns its domain part.
+
+To use this function, require @file{localdomain.mf} module
+(@pxref{Modules}), e.g.: @code{#require localdomain}.
@end deftypefn
@deftypefn {Built-in Function} number time ()
diff --git a/etc/mailfromd.rc b/etc/mailfromd.rc
index e19cac49..141e2632 100644
--- a/etc/mailfromd.rc
+++ b/etc/mailfromd.rc
@@ -15,8 +15,6 @@
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
-#error "Do not use this file 'AS IS'! Tailor it to suit your site!"
-
#pragma option relay "/etc/mail/sendmail.cw"
#pragma option relay "/etc/mail/relay-domains"
#pragma regex +extended +icase
@@ -24,14 +22,27 @@
#include_once <status.mfh>
#require dns
+#require localdomain
#require rateok
set mailfrom_address "<>"
-set ehlo_domain "your.domain"
+# If mailfromd does not determine local domain correctly, uncomment this
+# and replace DOMAIN with your local domain:
+#set ehlo_domain "DOMAIN"
number gltime interval("1 hour")
+
number need_greylist 0
+/* Begin block is executed at the beginning of each SMTP transaction.
+ */
+begin
+do
+ if %ehlo_domain == ""
+ set ehlo_domain localdomain()
+ fi
+done
+
func cachestr() returns string
do
if %cache_used
diff --git a/mfd/bi_gethostname.m4 b/mfd/bi_gethostname.m4
index 315a2d1b..fc7af790 100644
--- a/mfd/bi_gethostname.m4
+++ b/mfd/bi_gethostname.m4
@@ -30,7 +30,7 @@
This implementation is based on xgethostname by Jim Meyering
*/
-MF_DEFUN(gethostname, STRING)
+MF_DEFUN(gethostname, STRING, OPTIONAL, NUMBER dns)
{
size_t size = INITIAL_HOSTNAME_LENGTH;
@@ -72,6 +72,21 @@ MF_DEFUN(gethostname, STRING)
}
size = nsize;
}
+
+ if (MF_OPTVAL(dns)) {
+ struct hostent *hp;
+ char *ptr = MF_OBSTACK_BASE;
+
+ hp = gethostbyname(ptr);
+ if (hp) {
+ size_t nlen = strlen(hp->h_name);
+ if (nlen >= size)
+ MF_OBSTACK_GROW(NULL,
+ nlen - size + 1);
+ strcpy(ptr, hp->h_name);
+ }
+ }
+
MF_RETURN_OBSTACK();
}
END
diff --git a/mfd/gram.y b/mfd/gram.y
index 15ee9602..812eae39 100644
--- a/mfd/gram.y
+++ b/mfd/gram.y
@@ -401,7 +401,7 @@ _create_alias(void *item, void *data)
%type <state> state_ident
%type <matchtype> matches fnmatches
%type <type> retdecl
-%type <parmlist> params parmlist fparmlist parmdecl
+%type <parmlist> params opt_parmlist parmlist fparmlist parmdecl
%type <parm> parm
%type <function> fundecl
%type <value> value
@@ -669,17 +669,29 @@ params : fparmlist
$$.count = $$.optcount = 0;
$$.varargs = 1;
}
- | parmlist ';' fparmlist
+ | opt_parmlist ';' fparmlist
{
$1.count += $3.count;
$1.optcount = $3.count;
$1.varargs = $3.varargs;
+ if ($1.tail)
$1.tail->next = $3.head;
+ else
+ $1.head = $3.head;
$1.tail = $3.tail;
$$ = $1;
}
;
+opt_parmlist: /* empty */
+ {
+ $$.count = 0;
+ $$.varargs = 0;
+ $$.head = $$.tail = NULL;
+ }
+ | parmlist
+ ;
+
parmlist : parm
{
$$.count = 1;
@@ -3180,6 +3192,7 @@ mailfromd_test(int argc, char **argv)
env = create_environment(NULL,
dbg_dict_getsym, dbg_setreply, dbg_msgmod,
dict);
+ env_init(env);
xeval(env, smtp_state_begin);
env_init(env);
@@ -3220,9 +3233,11 @@ mailfromd_test(int argc, char **argv)
env_leave_frame(env, state_parms[test_state].cnt);
env_final_gc(env);
+ status = environment_get_status(env);
+
+ env_init(env);
xeval(env, smtp_state_end);
- status = environment_get_status(env);
printf("State %s: ", state_to_string(test_state));
print_stat(status);
printf("\n");
diff --git a/mfd/lex.l b/mfd/lex.l
index c1f9c3e8..da9dd1db 100644
--- a/mfd/lex.l
+++ b/mfd/lex.l
@@ -221,7 +221,10 @@ ICONST {LOCUS}|{VCONST}|{STATEDIR}|{PREPROC}
}
}
^[ \t]*#[ \t]*pragma[ \t].*/\n parse_pragma(yytext);
-^[ \t]*#[ \t]*error[ \t].*\n { parse_error("%s", yytext); advance_line(); }
+^[ \t]*#[ \t]*error[ \t].*\n {
+ yytext[yyleng-1] = 0; /* Kill trailing newline */
+ parse_error("%s", yytext);
+ advance_line(); }
/* End-of-line comments */
#.*\n { advance_line(); }
#.* /* end-of-file comment */;
diff --git a/mflib/Makefile.am b/mflib/Makefile.am
index 8afe000f..60c08a7f 100644
--- a/mflib/Makefile.am
+++ b/mflib/Makefile.am
@@ -20,6 +20,7 @@ inc_DATA =\
gettext.mf\
heloarg_test.mf\
is_ip.mf\
+ localdomain.mf\
match_cidr.mf\
match_dnsbl.mf\
match_rhsbl.mf\
diff --git a/mflib/localdomain.mf b/mflib/localdomain.mf
new file mode 100644
index 00000000..77f153e5
--- /dev/null
+++ b/mflib/localdomain.mf
@@ -0,0 +1,31 @@
+/* Local domain functions -*- mfl -*-
+ Copyright (C) 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/>. */
+
+func localdomain()
+ returns string
+do
+ string s getdomainname()
+ if %s == "" or %s == "(none)"
+ string h gethostname(1)
+ number i index(%h, ".")
+ if %h >= 0
+ set s substr(%h, %i + 1)
+ fi
+ fi
+ return %s
+done
+
+
diff --git a/mflib/safedb.mf4 b/mflib/safedb.mf4
index aaf10d51..d51e00ca 100644
--- a/mflib/safedb.mf4
+++ b/mflib/safedb.mf4
@@ -1,5 +1,5 @@
/* Safe DB I/O -*- mfl -*-
- Copyright (C) 2007, 2008 Sergey Poznyakoff
+ Copyright (C) 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
@@ -16,12 +16,17 @@
#include_once <status.mfh>
+number safedb_verbose
+
func safedbget(string name, string key ; string defval, number null)
returns string
do
catch e_dbfailure
do
- return ""
+ if %safedb_verbose
+ echo "safedbget: exception $1: $2"
+ fi
+ return %defval
done
if not defined(null)
set null 0
@@ -36,6 +41,9 @@ func safedbput(string name, string key, string value ; number null)
do
catch e_dbfailure
do
+ if %safedb_verbose
+ echo "safedbput: exception $1: $2"
+ fi
return
done
if not defined(null)
@@ -44,3 +52,39 @@ do
dbput(%name, %key, %value, %null)
done
+
+func safedbmap(string name, string key; number defval, number null)
+ returns number
+do
+ catch e_dbfailure
+ do
+ if %safedb_verbose
+ echo "safedbmap: exception $1: $2"
+ fi
+ return %defval
+ done
+ if not defined(defval)
+ set defval 0
+ fi
+ if not defined(null)
+ set null 0
+ fi
+ return dbmap(%name, %key, %null)
+done
+
+func safedbdel(string name, string key; number null)
+do
+ catch e_dbfailure
+ do
+ if %safedb_verbose
+ echo "safedbdel: exception $1: $2"
+ fi
+ return
+ done
+ if not defined(null)
+ set null 0
+ fi
+ return dbdel(%name, %key, %null)
+done
+
+

Return to:

Send suggestions and report system problems to the System administrator.