Re: [exim] Random number generation in an ACL

Top Page
Delete this message
Reply to this message
Author: Chris Lightfoot
Date:  
To: exim-users
Subject: Re: [exim] Random number generation in an ACL
On Thu, Jul 06, 2006 at 07:16:08PM +0200, Jakob Hirsch wrote:
> Ian P. Christian wrote:
>
> > To do this, I obviously need to generate a random number - is this possible in
> > the ACLs? I've hacked it in using perl at the moment, but I'm just curious as
>
> I don't think it's a good idea to do such stuff in the MTA, during SMTP
> connections. Anyway, this might help you:
> http://www.exim.org/mail-archives/exim-users/Week-of-Mon-20060109/msg00051.html


I don't think that would be a good idea for Ian's
application, since it would mean that his cleanup query
could be multiple times in a given second if there were
several incoming connections then (and I agree with you
about not doing this sort of thing at SMTP time).


If you can find a set of suitable variables, you could do
this with a message-digest function; for instance, if you
check that
    ${substr_0_3:${md5:...}}
is, say, `000', then that gives you odds of 1 in 4096 that
your function will be run. But that means finding a
suitable ... which varies enough. For instance, if you're
running your cleanup process from the connect ACL, you
could hash the time of day, process-ID, remote IP and
remote port, and you should be reasonably safe I suppose.


For finer control over the ratios, you can turn the
output of the hash function into a number with something
like,
    ${eval:(0x${substr_0_8:${md5:...}} / ...) }



Here's a patch (as yet untested) which would add a
$random_LOW_HIGH expansion pseudovariable to Exim:

--- expand.c.orig       2006-07-06 18:55:31.000000000 +0100
+++ expand.c    2006-07-06 19:05:00.000000000 +0100
@@ -2710,6 +2710,34 @@
         }
       }


+    /* Random number */
+    else if (Ustrncmp(name, "random_", 7) == 0)
+      {
+      /* Followed by lower and upper limit of number required. */
+      int low, high;
+      uschar *endptr, *p;
+      static int seeded;
+      if (!seeded)
+        {
+        srand(time(NULL));
+        seeded = 1;
+        }
+      low = (int)Ustrtol((const uschar *)name + 7, &endptr, 10);
+      if (endptr == name + 7 || *endptr != '_')
+        {
+        expand_string_message = "random_ must be followed by lower and upper limits";
+        return NULL;
+        }
+      p = endptr + 1;
+      high = (int)Ustrtol((const uschar *)endptr, &endptr, 10);
+      if (endptr == p || high <= low)
+        {
+        expand_string_message = "random_ must be followed by lower and upper limits";
+        return NULL;
+        }
+      value = string_sprintf("%d", low + (high - low) * (double)rand() / (RAND_MAX - 1.));
+      }
+
     /* Variable */


     else



--
``[To] call this novel formulaic is an insult
to the beauty and diversity of formulae.''
(Geoff Pullum reviews a Dan Brown novel)