aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2007-05-27 20:00:10 +0000
committerSergey Poznyakoff <gray@gnu.org.ua>2007-05-27 20:00:10 +0000
commit6bb637f647598002be3c8acfaf3b396966d3e581 (patch)
treeead65d2b207e8874684c558d4127e93a346ddc7d
parente3b13bbba66a92a75ac73d3ab50bca45d69c7c0d (diff)
downloadmailfromd-6bb637f647598002be3c8acfaf3b396966d3e581.tar.gz
mailfromd-6bb637f647598002be3c8acfaf3b396966d3e581.tar.bz2
Improve mfl-mode
git-svn-id: file:///svnroot/mailfromd/trunk@1479 7a8a7f39-df28-0410-adc6-e0d955640f24
-rw-r--r--ChangeLog15
-rw-r--r--NEWS11
-rw-r--r--doc/mailfromd.texi78
-rw-r--r--elisp/mfl-mode.el306
-rw-r--r--etc/mailfromd.rc95
-rw-r--r--tests/bctx00.at2
-rw-r--r--tests/etc/accept.rc3
-rw-r--r--tests/etc/ack.rc50
-rw-r--r--tests/etc/arg.rc40
-rw-r--r--tests/etc/catch.rc51
-rw-r--r--tests/etc/catch01.rc63
-rw-r--r--tests/etc/cidr.rc39
-rw-r--r--tests/etc/cond.rc55
-rw-r--r--tests/etc/dns.rc58
-rw-r--r--tests/etc/farg.rc41
-rw-r--r--tests/etc/greylist.rc43
-rw-r--r--tests/etc/macros.rc49
-rw-r--r--tests/etc/ml.rc1
-rw-r--r--tests/etc/numrcpt.rc39
-rw-r--r--tests/etc/poll-1.rc51
-rw-r--r--tests/etc/poll.rc49
-rw-r--r--tests/etc/prec.rc37
-rw-r--r--tests/etc/reject.rc3
-rw-r--r--tests/etc/relayed.rc40
-rw-r--r--tests/etc/sa01.rc39
-rw-r--r--tests/etc/sa02.rc39
-rw-r--r--tests/etc/sa03.rc41
-rw-r--r--tests/etc/sa04.rc41
-rw-r--r--tests/etc/shadow.rc47
-rw-r--r--tests/etc/strings.rc55
-rw-r--r--tests/etc/switch.rc79
-rw-r--r--tests/etc/tempfail.rc3
-rw-r--r--tests/etc/var.rc35
-rw-r--r--tests/fctx00.at2
-rw-r--r--tests/macros.at2
-rw-r--r--tests/shadow.at4
36 files changed, 977 insertions, 629 deletions
diff --git a/ChangeLog b/ChangeLog
index ca710d51..f97a4dc0 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,18 @@
+2007-05-27 Sergey Poznyakoff <gray@gnu.org.ua>
+
+ * elisp/mfl-mode.el: Initial implementation
+ * tests/shadow.at, tests/bctx00.at, tests/fctx00.at,
+ tests/macros.at, tests/etc/reject.rc, tests/etc/farg.rc,
+ tests/etc/cidr.rc, tests/etc/catch.rc, tests/etc/catch01.rc,
+ tests/etc/cond.rc, tests/etc/dns.rc, tests/etc/macros.rc,
+ tests/etc/shadow.rc, tests/etc/relayed.rc, tests/etc/var.rc,
+ tests/etc/numrcpt.rc, tests/etc/strings.rc, tests/etc/prec.rc,
+ tests/etc/ack.rc, tests/etc/accept.rc, tests/etc/switch.rc,
+ tests/etc/tempfail.rc, tests/etc/greylist.rc, tests/etc/poll-1.rc,
+ tests/etc/sa01.rc, tests/etc/sa02.rc, tests/etc/poll.rc,
+ tests/etc/sa03.rc, tests/etc/sa04.rc, tests/etc/ml.rc,
+ tests/etc/arg.rc, etc/mailfromd.rc: Use MFL Emacs mode
+
2007-05-26 Sergey Poznyakoff <gray@gnu.org.ua>
* doc/mailfromd.texi: Update
diff --git a/NEWS b/NEWS
index 88d738c5..b93cdf7d 100644
--- a/NEWS
+++ b/NEWS
@@ -1,4 +1,4 @@
-Mailfromd NEWS -- history of user-visible changes. 2007-05-24
+Mailfromd NEWS -- history of user-visible changes. 2007-05-27
Copyright (C) 2005, 2006, 2007 Sergey Poznyakoff
See the end of file for copying conditions.
@@ -19,6 +19,15 @@ language. The following functions are implemented: bindtextdomain,
dgettext, dngettext, textdomain, gettext, ngettext. In addition,
macros _() and N_() are also provided.
+* GNU Emacs MFL Mode
+
+This release comes with the file `mfl-mode.el', providing MFL mode for
+GNU Emacs. This mode facilitates editing MFL source files. By
+default, the new mode is installed whenever configure determines the
+presense of GNU Emacs on your machine. See the documentation, node
+`Using MFL Mode' for the detailed discussion of this mode including
+customization information.
+
* Input files are preprocessed before compilation. Default preprocessor is
M4, but this can be changed (or disabled) at configuration time (see
`DEFAULT_PREPROCESSOR' variable and `--with-preprocessor' command
diff --git a/doc/mailfromd.texi b/doc/mailfromd.texi
index 4b2f14ac..30f542c3 100644
--- a/doc/mailfromd.texi
+++ b/doc/mailfromd.texi
@@ -97,6 +97,7 @@ documents @command{mailfromd} Version @value{VERSION}.
* Building:: Building the Package.
* Tutorial:: Mailfromd Tutorial.
* MFL:: The Mail Filtering Language.
+* Using MFL Mode:: Using the GNU Emacs MFL Mode.
* Mailfromd Configuration:: Configuring @command{mailfromd}.
* Sendmail Configuration:: Configuring Sendmail to use @command{mailfromd}.
* mtasim:: An @acronym{MTA} simulator.
@@ -3274,7 +3275,7 @@ used as a literal, or to require the corresponding module
(@pxref{Modules}) (or include the source file directly,
@pxref{include}), if it is indeed a function name.
-@node MFL, Mailfromd Configuration, Tutorial, Top
+@node MFL, Using MFL Mode, Tutorial, Top
@chapter Mail Filtering Language
@cindex MFL
@cindex mail filtering language
@@ -9552,7 +9553,80 @@ are keywords in @code{on} context:
@item poll
@end itemize
-@node Mailfromd Configuration, Sendmail Configuration, MFL, Top
+@node Using MFL Mode, Mailfromd Configuration, MFL, Top
+@chapter Using the GNU Emacs MFL Mode
+@UNREVISED{}
+@cindex Emacs, @acronym{MFL} mode
+@cindex GNU Emacs, @acronym{MFL} mode
+@cindex @acronym{MFL} mode, GNU Emacs
+ @acronym{MFL} sources are usual @acronym{ASCII} files and you may
+edit them with any editor you like. However, the best choice for this
+job (as well as for many others) is, without doubt, GNU Emacs. To ease
+the work of editing script files, the @command{mailfromd} package
+provides a special Emacs mode, called @acronym{MFL} mode.
+
+@flindex mfl-mode.el
+@flindex site-start.el
+@flindex ~/.emacs
+@cindex Enabling @acronym{MFL} mode
+@cindex @acronym{MFL} mode, enabling
+@cindex MFL mode,
+ The elisp source file providing this mode, @file{mfl-mode.el}, is
+installed automatically, provided that GNU Emacs is present on your
+machine. To enable the mode, add the following to your Emacs setup
+file (either system-wide @file{site-start.el}, or your personal one,
+@file{~/.emacs}):
+
+@smalllisp
+@group
+(autoload 'mfl-mode "mfl-mode")
+(setq auto-mode-alist (append auto-mode-alist
+ '(("/usr/local/etc/mailfromd.rc" . mfl-mode)
+ ("\\.mf$" . mfl-mode))))
+@end group
+@end smalllisp
+
+ The first line loads the @acronym{MFL} mode, and the second one
+tells Emacs to apply it to the file @file{/usr/local/etc/mailfromd.rc}
+(of course, you should replace @file{/usr/local/etc/} with the exact
+location, where your main filter script file is installed), and to any
+file whose name ends with a @samp{.mf} suffix.
+
+ @acronym{MFL} mode provides automatic indentation and syntax
+highlighting for @acronym{MFL} sources.
+
+@cindex Finding function definition
+@cindex Navigating through function definitions
+ The mode provides two special commands that help navigate through
+the complex filter scripts:
+
+@table @kbd
+@item C-M-a
+Move to the beginning of current function or handler definition.
+
+@item C-M-e
+Move to the end of current function or handler definition.
+@end table
+
+ Here, @dfn{current function or handler} means the one within which
+your cursor currently stays.
+
+ You can use @kbd{C-M-e} repeatedly to walk through all function
+and handler definitions in your script files. Similarly, repeatedly
+pressing @kbd{C-M-a} will visit all the definitions in the opposite
+direction (from the last up to the very first one).
+
+@cindex Verifying script syntax
+ Another special command, @kbd{C-c C-c}, allows to to verify the
+syntax of your script file. This command runs @command{mailfromd} in
+syntax check mode (@pxref{Testing Filter Scripts}) and displays its
+output in a secondary window, which allows to navigate through
+eventual diagnostic messages and to jump to the source locations
+described by them.
+
+
+
+@node Mailfromd Configuration, Sendmail Configuration, Using MFL Mode, Top
@chapter Configuring @command{mailfromd}
In the simplest case you will be able to startup
diff --git a/elisp/mfl-mode.el b/elisp/mfl-mode.el
index 5c66edc6..aadcab08 100644
--- a/elisp/mfl-mode.el
+++ b/elisp/mfl-mode.el
@@ -29,6 +29,12 @@
;; Install the file mfl-mode.elc (and, optionally, mfl-mode.el) to
;; any directory in your Emacs load-path.
+;; Customization:
+;; To your .emacs or site-start.el add:
+;; (autoload 'mfl-mode "mfl-mode")
+;; (setq auto-mode-alist (append auto-mode-alist
+;; '(("\\.mf$" . mfl-mode))))
+
(eval-when-compile
;; We use functions from these modules
(mapcar 'require '(font-lock)))
@@ -51,12 +57,232 @@
(modify-syntax-entry ?\/ ". 14" mfl-mode-syntax-table)
(modify-syntax-entry ?\* ". 23" mfl-mode-syntax-table))
-(defvar mfl-mode-map (make-sparse-keymap)
+(defvar mfl-mode-map nil
"Keymap used in MFL mode.")
-;(define-key mfl-mode-map [menu-bar] (make-sparse-keymap))
-;(define-key cflow-mode-map [menu-bar MFL]
-; (cons "MFL" (make-sparse-keymap "MFL")))
+(unless mfl-mode-map
+ (setq mfl-mode-map (make-sparse-keymap))
+ (define-key mfl-mode-map "\t" 'mfl-indent-line)
+ (define-key mfl-mode-map "\r" 'mfl-newline-and-indent)
+ (define-key mfl-mode-map "\C-c\C-c" 'mfl-check-syntax)
+ (define-key mfl-mode-map "\C-\M-a" 'beginning-of-defun)
+ (define-key mfl-mode-map "\C-\M-e" 'end-of-defun)
+
+ (define-key mfl-mode-map [menu-bar] (make-sparse-keymap))
+ (define-key mfl-mode-map [menu-bar MFL]
+ (cons "MFL" mfl-mode-map))
+ (define-key mfl-mode-map [mfl-check-syntax]
+ '("Check syntax" . mfl-check-syntax))
+ (define-key mfl-mode-map [beginning-of-defun]
+ '("Beginning of definition" . beginning-of-defun))
+ (define-key mfl-mode-map [end-of-defun]
+ '("End of definition" . beginning-of-defun)))
+
+
+
+(defgroup mfl nil
+ "MFL programming utilities"
+ :group 'unix
+ :group 'languages)
+
+(defgroup mfl nil
+ "MFL script mode"
+ :group 'mfl
+ :prefix "mfl-")
+
+(defgroup mfl-lint nil
+ "Variables controlling invocation of mailfromd in `lint' mode.
+"
+ :group 'mfl)
+
+(defcustom mfl-mailfromd-command "mailfromd"
+ "*The default mailfromd command line (without --lint option)"
+ :type 'string
+ :group 'mfl-lint)
+
+(defcustom mfl-include-path nil
+ "*Additional include directories"
+ :type '(repeat string)
+ :group 'mfl-lint)
+
+(defgroup mfl-indentation nil
+ "Variables controlling indentation in MFL scripts.
+"
+ :group 'mfl)
+
+(defcustom mfl-basic-offset 2
+ "*The default indentation increment."
+ :type 'integer
+ :group 'mfl-indentation)
+
+(defcustom mfl-case-line-offset 0
+ "*The default indentation increment for `when' and `case' lines."
+ :type 'integer
+ :group 'mfl-indentation)
+
+(defun mfl-find-comment-start ()
+ "Find the beginning of a multiline comment the point is in."
+ (while (not (or (bobp) (looking-at ".*/\\*")))
+ (forward-line -1)))
+
+(defun mfl-next-line-indentation ()
+ "Guess and return the indentation of the next line."
+ (save-excursion
+ (beginning-of-line)
+ (cond
+ ((not (eolp))
+ (skip-chars-forward " \t")
+ (cond
+ ((looking-at (regexp-opt '("do" "if" "else" "elif") 'words))
+ (+ (current-indentation) mfl-basic-offset))
+ ((looking-at ".*/\\*")
+ (+ (current-indentation)
+ (- (match-end 0) (match-beginning 0)) 1)) ; FIXME: customization
+ ((looking-at ".*\\*/\\s *$")
+ (mfl-find-comment-start)
+ (forward-line -1)
+ (current-indentation))
+ ((looking-at ".*:[ \t]*$")
+ (+ (current-indentation) mfl-basic-offset))
+ (t
+ (current-indentation))))
+ (t
+ (forward-line -1)
+ (mfl-next-line-indentation)))))
+
+(defun mfl-find-line-indentation (regexp)
+ "Move backwards to the line containing "REGEXP", skipping over
+block constructs. Return the indentation of the line, or 0
+if no matching line was found."
+ (catch 'found
+ (while (not (bobp))
+ (forward-line -1)
+ (beginning-of-line)
+ (skip-chars-forward " \t")
+ (cond
+ ((looking-at regexp)
+ (throw 'found (current-indentation)))
+ ((looking-at "\\<done\\>")
+ (mfl-find-line-indent "\\<do\\>"))
+ ((looking-at "\\<fi\\>")
+ (mfl-find-line-indent "\\<if\\>"))))
+ 0))
+
+(defun mfl-find-line-forward (regexp)
+ "Move forward to the line containing "REGEXP", skipping over
+block constructs. Return t if the line was found, nil otherwise."
+ (catch 'found
+ (while (not (eobp))
+ (forward-line 1)
+ (beginning-of-line)
+ (skip-chars-forward " \t")
+ (cond
+ ((looking-at regexp)
+ (throw 'found t))
+ ((looking-at "\\<do\\>")
+ (mfl-find-line-forward "\\<done\\>"))
+ ((looking-at "\\<if\\>")
+ (mfl-find-line-forward "\\<fi\\>"))))
+ nil))
+
+(defun mfl-compute-line-indentation ()
+ "Compute the indentation of the current line."
+ (save-excursion
+ (beginning-of-line)
+ (skip-chars-forward " \t")
+ (cond
+ ((looking-at (regexp-opt '("else" "elif" "fi") 'words))
+ (mfl-find-line-indentation (regexp-opt '("if" "elif") 'words)))
+ ((looking-at "\\<done\\>")
+ ; FIXME: Continuation lines are not properly handled
+ (mfl-find-line-indentation ".*\\<do\\>"))
+ ((looking-at "\\<when\\>")
+ (+ (mfl-find-line-indentation "\\<on\\>")
+ mfl-case-line-offset))
+ ((looking-at (regexp-opt '("case" "default") 'words))
+ (+ (mfl-find-line-indentation "\\<switch\\>")
+ mfl-case-line-offset))
+ (t
+ (forward-line -1)
+ (mfl-next-line-indentation)))))
+
+(defun mfl-indent-line ()
+ "Indent the current line."
+ (interactive "*")
+ (let ((start-of-line (save-excursion
+ (beginning-of-line)
+ (skip-chars-forward " \t")
+ (point)))
+ (shift-amt (mfl-compute-line-indentation)))
+ (if (not (= shift-amt (current-indentation)))
+ (let ((off (- (point) start-of-line)))
+ (beginning-of-line)
+ (delete-region (point) start-of-line)
+ (indent-to shift-amt)
+ (if (>= off 0)
+ (goto-char (+ (point) off))
+ (beginning-of-line))))))
+
+(defun mfl-newline-and-indent ()
+ "Indent the current line, insert a newline, and then indent again."
+ (interactive "*")
+ (mfl-indent-line)
+ (newline-and-indent))
+
+
+(defun mfl-check-syntax ()
+ "Checks the syntax of the current MFL buffer."
+ (interactive "*")
+ (compile (concat
+ mfl-mailfromd-command
+ " --lint"
+ (if mfl-include-path
+ (apply 'concat (mapcar (lambda (x) (concat " -I" x))
+ mfl-include-path))
+ "")
+ " "
+ (buffer-file-name))))
+
+
+
+(defun mfl-at-beginning-of-defun-p ()
+ "Return true if the point is at the beginning of a defun"
+ (or (looking-at "[ \t]*prog [a-z]+")
+ (looking-at (concat "[ \t]*"
+ (regexp-opt '("begin" "end") 'words)))
+ (looking-at "[ \t]*func\\s +[a-zA-Z_][a-zA-Z0-9_]*\\s *(")))
+
+(defun mfl-search-next-defun ()
+ "If the point is at the beginning of a defun, return t. Otherwise,
+move forward to the beginning of a next defun. Return t on success, nil
+otherwise."
+ (catch 'loop
+ (while (not (eobp))
+ (if (mfl-at-beginning-of-defun-p)
+ (throw 'loop t))
+ (forward-line 1))
+ nil))
+
+(defun mfl-beginning-of-defun ()
+ "Interface to `beginning-of-defun'"
+ (catch 'loop
+ (while (not (bobp))
+ (forward-line -1)
+ (if (mfl-at-beginning-of-defun-p)
+ (throw 'loop t)))
+ nil))
+
+(defun mfl-end-of-defun-function ()
+ "Interface to `end-of-defun'"
+ (let ((pos (save-excursion
+ (and (mfl-search-next-defun)
+ (mfl-find-line-forward "\\<do\\>")
+ (mfl-find-line-forward "\\<done\\>")
+ (forward-line 1)
+ (point)))))
+ (if pos
+ (goto-char pos)
+ pos)))
(defconst mfl-keywords
@@ -70,24 +296,27 @@
"not" "on" "or" "pass"
"prog" "reject" "replace" "return"
"returns" "set" "switch" "tempfail"
- "throw" "when" "while"
- ;; FIXME: These are context-dependent
- "as" "from" "host" "poll"))))
+ "throw" "when" "while") 'words)))
+
+(defconst mfl-on-keywords
+ ;; context-dependent keywords
+ (eval-when-compile
+ (regexp-opt '("as" "from" "host" "poll") 'words)))
(defconst mfl-constants
(eval-when-compile
(regexp-opt '("__file__" "__function__" "__line__" "__major__"
"__minor__" "__package__" "__patch__" "__preproc__"
- "__version__"))))
+ "__version__") 'words)))
(defconst mfl-type-names
(eval-when-compile
- (regexp-opt '("number" "string"))))
+ (regexp-opt '("number" "string") 'words)))
(defconst mfl-preprocessor-directives
(eval-when-compile
(regexp-opt '("include" "include_once" "error" "line"
- "pragma" "require" "warning"))))
+ "pragma" "require" "warning") 'words)))
(defconst mfl-m4-keywords
(eval-when-compile
@@ -101,13 +330,21 @@
"m4_pushdef" "m4_regexp" "m4_shift" "m4_sinclude"
"m4_substr" "m4_symbols" "m4_syscmd" "m4_sysval"
"m4_traceoff" "m4_traceon" "m4_translit" "m4_undivert"
- "m4_dnl" "m4___line__" "m4___file__"))))
+ "m4_dnl" "m4___line__" "m4___file__") 'words)))
(defconst mfl-macros
(eval-when-compile
- (regexp-opt '("defined" "printf" "_" "N_"))))
+ (regexp-opt '("defined" "printf" "_" "N_") 'words)))
+
+(defconst mfl-status-codes
+ (eval-when-compile
+ (regexp-opt '("success" "not_found" "failure" "temp_failure"
+ "ston_conv" "divzero" "regcomp" "invip"
+ "invcidr" "invtime" "dbfailure" "range"
+ "url" "noresolve" "ioerr") 'words)))
+
;; Font-lock stuff
(defconst mfl-font-lock-keywords
(eval-when-compile
@@ -124,22 +361,27 @@
2 font-lock-string-face)
;; Fontify otherwise as symbol names, and the preprocessor directive
;; names.
- (list
- (concat "^#[ \t]*\\(" mfl-preprocessor-directives
+ (list
+ (concat "^#[ \t]*\\(" mfl-preprocessor-directives
"\\)\\>[ \t!]*\\(\\sw+\\)?")
'(1 font-lock-builtin-face))
;; Otherwise, fontify #...\n as comments:
- (list
- "^#\\(.*\\)\n" 1 font-lock-comment-face)
-
+ (list
+ "^#\\(.*\\)\n" 1 font-lock-comment-face)
+
;; Fontify all type names.
`(eval .
(cons (concat "\\<\\(" ,mfl-type-names "\\)\\>") 'font-lock-type-face))
+ ;; Fontify exception and status codes
+ `(eval .
+ (cons (concat "\\<\\(" ,mfl-status-codes "\\)\\>")
+ 'font-lock-constant-face))
+
;;
;; Fontify all builtin keywords
(concat "\\<\\(" mfl-keywords "\\)\\>")
-
+
;; Fontify m4 keywords and macros
(list
(concat "\\<\\(" mfl-m4-keywords "\\)\\>")
@@ -156,15 +398,30 @@
"defined[ \t]*([ \t]*\\([a-zA-Z0-9_]+\\)[ \t]*)"
1 font-lock-variable-name-face)
(list
- (concat "\\<\\(" mfl-type-names "\\)\\>[ \t]+\\([a-zA-Z0-9_]+\\)")
+ (concat mfl-type-names "[ \t]+\\([a-zA-Z0-9_]+\\)")
2 font-lock-variable-name-face)
;; Fontify macro names
(list
"${?\\([a-zA-Z0-9_]+\\)}?"
1 font-lock-constant-face)
+
+ ;; Fontify `on poll' statement
+ (list
+ (concat "\\<on\\>.*\\(" mfl-on-keywords "\\)")
+ 1 font-lock-keyword-face)
+
+ (list
+ (concat "\\<on\\>.*" mfl-on-keywords ".*\\(" mfl-on-keywords "\\)")
+ 1 font-lock-keyword-face)
+
+ (list
+ (concat "\\<on\\>.*" mfl-on-keywords ".*" mfl-on-keywords ".*\\(" mfl-on-keywords "\\)")
+ 1 font-lock-keyword-face)
+
+ ;; FIXME: Fontify preprocessor quotes
)))
-
+
;;;###autoload
(defun mfl-mode ()
"Major mode for viewing cflow output files
@@ -175,11 +432,18 @@ Key bindings are:
(interactive)
(kill-all-local-variables)
(use-local-map mfl-mode-map)
+ (make-local-variable 'beginning-of-defun-function)
+ (make-local-variable 'end-of-defun-function)
+
(setq major-mode 'mfl-mode
- mode-name "MFL")
+ mode-name "MFL"
+ beginning-of-defun-function 'mfl-beginning-of-defun
+ end-of-defun-function 'mfl-end-of-defun-function
+ indent-line-function 'mfl-indent-line)
(set-syntax-table mfl-mode-syntax-table)
+
(make-local-variable 'font-lock-defaults)
(setq font-lock-defaults
'((mfl-font-lock-keywords) nil nil
diff --git a/etc/mailfromd.rc b/etc/mailfromd.rc
index 8d9a55ac..ab684b8e 100644
--- a/etc/mailfromd.rc
+++ b/etc/mailfromd.rc
@@ -1,4 +1,4 @@
-/* This is a sample start-up script for mailfromd.
+/* This is a sample start-up script for mailfromd. -*- mfl -*-
Site administrators are urged to write nicer versions.
Copyright (C) 2005, 2006, 2007 Sergey Poznyakoff
@@ -37,64 +37,65 @@ set need_greylist 0
func cachestr() returns string
do
- if %cache_used
- return "[CACHED] "
- else
- return ""
- fi
+ if %cache_used
+ return "[CACHED] "
+ else
+ return ""
+ fi
done
prog envfrom
do
- if $f = ""
- pass
- elif hostname ${client_addr} matches ".*(adsl|sdsl|hdsl|ldsl|dialin|dialup|ppp|dhcp|dynamic).*"
- reject 550 5.7.1 "Use your SMTP relay"
- elif hostname ${client_addr} matches ".*-[0-9]{1,3}-[0-9]{1,3}-[0-9]{1,3}-[0-9]{1,3}.*"
- on poll host ${client_addr} for $f do
- when success:
- pass
- when not_found or failure:
- reject 550 5.1.0 cachestr() "Sender validity not confirmed"
- when temp_failure:
- tempfail 450 4.1.0 "Try again later"
- done
- elif relayed hostname ${client_addr}
- pass
- elif $f mx fnmatches "*.yahoo.com"
- or $f mx fnmatches "*.namaeserver.com"
- set need_greylist 1
- else
- on poll $f do
- when success:
- pass
- when not_found or failure:
- reject 550 5.1.0 cachestr() "Sender validity not confirmed"
- when temp_failure:
- tempfail
- done
- fi
+ if $f = ""
+ pass
+ elif hostname ${client_addr} matches ".*(adsl|sdsl|hdsl|ldsl|dialin|dialup|ppp|dhcp|dynamic).*"
+ reject 550 5.7.1 "Use your SMTP relay"
+ elif hostname ${client_addr} matches ".*-[0-9]{1,3}-[0-9]{1,3}-[0-9]{1,3}-[0-9]{1,3}.*"
+ on poll host ${client_addr} for $f
+ do
+ when success:
+ pass
+ when not_found or failure:
+ reject 550 5.1.0 cachestr() "Sender validity not confirmed"
+ when temp_failure:
+ tempfail 450 4.1.0 "Try again later"
+ done
+ elif relayed hostname ${client_addr}
+ pass
+ elif $f mx fnmatches "*.yahoo.com"
+ or $f mx fnmatches "*.namaeserver.com"
+ set need_greylist 1
+ else
+ on poll $f do
+ when success:
+ pass
+ when not_found or failure:
+ reject 550 5.1.0 cachestr() "Sender validity not confirmed"
+ when temp_failure:
+ tempfail
+ done
+ fi
- if rate($f "-" ${client_addr}, interval("1 hour 30 minutes")) > 100
- tempfail 450 4.7.0 "Mail sending rate exceeded. Try again later"
- fi
+ if rate($f "-" ${client_addr}, interval("1 hour 30 minutes")) > 100
+ tempfail 450 4.7.0 "Mail sending rate exceeded. Try again later"
+ fi
done
prog envrcpt
do
- if %need_greylist
- and not dbmap("/var/run/whitelist.db", $client_addr)
- if greylist($client_addr "-" $f "-" $rcpt_addr, %gltime)
- if %greylist_seconds_left = %gltime
- tempfail 450 4.7.0
- "You are greylisted for " %gltime " seconds"
- else
- tempfail 450 4.7.0
+ if %need_greylist
+ and not dbmap("/var/run/whitelist.db", $client_addr)
+ if greylist($client_addr "-" $f "-" $rcpt_addr, %gltime)
+ if %greylist_seconds_left = %gltime
+ tempfail 450 4.7.0
+ "You are greylisted for " %gltime " seconds"
+ else
+ tempfail 450 4.7.0
"Still greylisted for "
%greylist_seconds_left " seconds"
- fi
fi
- fi
+ fi
+ fi
done
diff --git a/tests/bctx00.at b/tests/bctx00.at
index 8388ba8a..d52dab92 100644
--- a/tests/bctx00.at
+++ b/tests/bctx00.at
@@ -19,7 +19,7 @@
AT_SETUP([Builtin in wrong context])
AT_KEYWORDS([context builtin-context bctx bctx00])
-echo "mailfromd: $ETCDIR/sa01.rc:21: Built-in function \`sa' cannot be used in prog \`envfrom'" > experr
+echo "mailfromd: $ETCDIR/sa01.rc:20: Built-in function \`sa' cannot be used in prog \`envfrom'" > experr
AT_CHECK([mailfromd $MFOPTS --test $ETCDIR/sa01.rc],
[78],
diff --git a/tests/etc/accept.rc b/tests/etc/accept.rc
index 05252432..58f0ae74 100644
--- a/tests/etc/accept.rc
+++ b/tests/etc/accept.rc
@@ -1,4 +1,5 @@
+/* -*- mfl -*- */
prog envfrom
do
- accept
+ accept
done
diff --git a/tests/etc/ack.rc b/tests/etc/ack.rc
index 6a3f76c4..66c1a6c8 100644
--- a/tests/etc/ack.rc
+++ b/tests/etc/ack.rc
@@ -1,20 +1,20 @@
-# This file is part of Mailfromd
-# Copyright (C) 2006, 2007 Sergey Poznyakoff
-#
-# Mailfromd 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 2 of the License, or
-# (at your option) any later version.
-#
-# Mailfromd 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 Mailfromd; if not, write to the Free Software Foundation,
-# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-#
+/* This file is part of Mailfromd -*- mfl -*-
+ Copyright (C) 2006, 2007 Sergey Poznyakoff
+
+ Mailfromd 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 2 of the License, or
+ (at your option) any later version.
+
+ Mailfromd 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 Mailfromd; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
+
/* This test computes the value of Ackerman function ack(3,8), which
requires 2785999 calls of ack(). Maximum recursion depth is 2047,
@@ -25,18 +25,18 @@
func ack(number