8f5960e
diff --git a/hosts_access.c b/hosts_access.c
8f5960e
index dfff943..13ad9f9 100644
8f5960e
--- a/hosts_access.c
8f5960e
+++ b/hosts_access.c
8f5960e
@@ -78,6 +78,9 @@ int     hosts_access_verbose = 0;
8f5960e
   */
8f5960e
 
8f5960e
 int     resident = (-1);		/* -1, 0: unknown; +1: yes */
8f5960e
+#ifdef ACLEXEC
8f5960e
+int	aclexec_matched = 0;
8f5960e
+#endif
8f5960e
 
8f5960e
 /* Forward declarations. */
8f5960e
 
8f5960e
@@ -179,6 +182,12 @@ struct request_info *request;
8f5960e
 	if (sh_cmd) {
8f5960e
 #ifdef PROCESS_OPTIONS
8f5960e
 	    process_options(sh_cmd, request);
8f5960e
+# ifdef ACLEXEC
8f5960e
+	    if (aclexec_matched) {
8f5960e
+		syslog(LOG_INFO, "aclexec returned %d", aclexec_matched);
8f5960e
+		match = NO;
8f5960e
+	    }
8f5960e
+# endif
8f5960e
 #else
8f5960e
 	    char    cmd[BUFSIZ];
8f5960e
 	    shell_cmd(percent_x(cmd, sizeof(cmd), sh_cmd, request));
8f5960e
diff --git a/hosts_options.5 b/hosts_options.5
8f5960e
index 3bd189e..39c7fdd 100644
8f5960e
--- a/hosts_options.5
8f5960e
+++ b/hosts_options.5
8f5960e
@@ -54,6 +54,23 @@ ALL: ALL: ALLOW
8f5960e
 .sp
8f5960e
 Notice the leading dot on the domain name patterns.
8f5960e
 .SH RUNNING OTHER COMMANDS
8f5960e
+.IP "aclexec shell_command"
8f5960e
+Execute, in a child process, the specified shell command, after
8f5960e
+performing the %<letter> expansions described in the hosts_access(5)
8f5960e
+manual page.  The command is executed with stdin, stdout and stderr
8f5960e
+connected to the null device, so that it won't mess up the
8f5960e
+conversation with the client host. Example:
8f5960e
+.sp
8f5960e
+.nf
8f5960e
+.ti +3
8f5960e
+smtp : ALL : aclexec checkdnsbl %a
8f5960e
+.fi
8f5960e
+.sp
8f5960e
+executes, in a background child process, the shell command "checkdnsbl %a"
8f5960e
+after replacing %a by the address of the remote host.
8f5960e
+.sp
8f5960e
+The connection will be allowed or refused depending on whether the
8f5960e
+command returns a true or false exit status.
8f5960e
 .IP "spawn shell_command"
8f5960e
 Execute, in a child process, the specified shell command, after
8f5960e
 performing the %<letter> expansions described in the hosts_access(5)
8f5960e
diff --git a/options.c b/options.c
8f5960e
index 675c9b4..b01db51 100644
8f5960e
--- a/options.c
8f5960e
+++ b/options.c
8f5960e
@@ -49,6 +49,7 @@ static char sccsid[] = "@(#) options.c 1.17 96/02/11 17:01:31";
8f5960e
 #include <setjmp.h>
8f5960e
 #include <string.h>
8f5960e
 #include <unistd.h>
8f5960e
+#include <sys/wait.h>
8f5960e
 
8f5960e
 #ifndef MAXPATHNAMELEN
8f5960e
 #define MAXPATHNAMELEN  BUFSIZ
8f5960e
@@ -78,6 +79,7 @@ static void group_option();		/* execute "group name" option */
8f5960e
 static void umask_option();		/* execute "umask mask" option */
8f5960e
 static void linger_option();		/* execute "linger time" option */
8f5960e
 static void keepalive_option();		/* execute "keepalive" option */
8f5960e
+static void aclexec_option();		/* execute "aclexec command" option */
8f5960e
 static void spawn_option();		/* execute "spawn command" option */
8f5960e
 static void twist_option();		/* execute "twist command" option */
8f5960e
 static void rfc931_option();		/* execute "rfc931" option */
8f5960e
@@ -115,6 +117,9 @@ static struct option option_table[] = {
8f5960e
     { "umask", umask_option, NEED_ARG },
8f5960e
     { "linger", linger_option, NEED_ARG },
8f5960e
     { "keepalive", keepalive_option, 0 },
8f5960e
+#ifdef ACLEXEC
8f5960e
+    { "aclexec", aclexec_option, NEED_ARG | EXPAND_ARG },
8f5960e
+#endif
8f5960e
     { "spawn", spawn_option, NEED_ARG | EXPAND_ARG },
8f5960e
     { "twist", twist_option, NEED_ARG | EXPAND_ARG | USE_LAST },
8f5960e
     { "rfc931", rfc931_option, OPT_ARG },
8f5960e
@@ -327,6 +332,54 @@ struct request_info *request;
8f5960e
 	shell_cmd(value);
8f5960e
 }
8f5960e
 
8f5960e
+#ifdef ACLEXEC
8f5960e
+/* aclexec_option - spawn a shell command and check status */
8f5960e
+
8f5960e
+/* ARGSUSED */
8f5960e
+
8f5960e
+static void aclexec_option(value, request)
8f5960e
+char   *value;
8f5960e
+struct request_info *request;
8f5960e
+{
8f5960e
+    int status, child_pid, wait_pid;
8f5960e
+    extern int aclexec_matched;
8f5960e
+
8f5960e
+    if (dry_run != 0)
8f5960e
+	    return;
8f5960e
+
8f5960e
+    child_pid = fork();
8f5960e
+
8f5960e
+    /* Something went wrong: we MUST terminate the process. */
8f5960e
+    if (child_pid < 0) {
8f5960e
+	tcpd_warn("aclexec_option: /bin/sh: %m");
8f5960e
+	clean_exit(request);
8f5960e
+    }
8f5960e
+
8f5960e
+    if (child_pid == 0) {
8f5960e
+	execl("/bin/sh", "sh", "-c", value, (char *) 0);
8f5960e
+
8f5960e
+        /* Something went wrong. We MUST terminate the child process. */
8f5960e
+        tcpd_warn("execl /bin/sh: %m");
8f5960e
+	_exit(0);
8f5960e
+    }
8f5960e
+
8f5960e
+    while ((wait_pid = wait(&status)) != -1 && wait_pid != child_pid)
8f5960e
+	/* void */ ;
8f5960e
+
8f5960e
+    aclexec_matched = 1;
8f5960e
+
8f5960e
+    if (WIFEXITED(status) && WEXITSTATUS(status) == 0) {
8f5960e
+	aclexec_matched = 0;
8f5960e
+    }
8f5960e
+
8f5960e
+    if (WIFSIGNALED(status))
8f5960e
+	tcpd_warn("process %d exited with signal %d", child_pid,
8f5960e
+	    WTERMSIG(status));
8f5960e
+
8f5960e
+    return;
8f5960e
+}
8f5960e
+#endif
8f5960e
+
8f5960e
 /* linger_option - set the socket linger time (Marc Boucher <marc@cam.org>) */
8f5960e
 
8f5960e
 /* ARGSUSED */
8f5960e
diff --git a/tcpdchk.c b/tcpdchk.c
8f5960e
index e67ffb0..8c74df8 100644
8f5960e
--- a/tcpdchk.c
8f5960e
+++ b/tcpdchk.c
8f5960e
@@ -59,10 +59,6 @@ static char sep[] = ", \t\n";
8f5960e
 
8f5960e
 #define	BUFLEN 2048
8f5960e
 
8f5960e
-int     resident = 0;
8f5960e
-int     hosts_access_verbose = 0;
8f5960e
-char   *hosts_allow_table = HOSTS_ALLOW;
8f5960e
-char   *hosts_deny_table = HOSTS_DENY;
8f5960e
 extern jmp_buf tcpd_buf;
8f5960e
 
8f5960e
  /*
8f5960e
-- 
8f5960e
2.1.0
8f5960e