Add tls_dh_max_bits to OptionLists.txt
[exim.git] / src / src / expand.c
index e847fb798b76de3e624e5e8363895b6bae5af53e..84167b688d60c756ac0eac726622e7c7c99963b8 100644 (file)
@@ -2,7 +2,7 @@
 *     Exim - an Internet mail transport agent    *
 *************************************************/
 
-/* Copyright (c) University of Cambridge 1995 - 2009 */
+/* Copyright (c) University of Cambridge 1995 - 2012 */
 /* See the file NOTICE for conditions of use and distribution. */
 
 
@@ -363,6 +363,7 @@ enum {
                         /* local_scan()) */
   vtype_todbsdin,       /* value not used; generate BSD inbox tod */
   vtype_tode,           /* value not used; generate tod in epoch format */
+  vtype_todel,          /* value not used; generate tod in epoch/usec format */
   vtype_todf,           /* value not used; generate full tod */
   vtype_todl,           /* value not used; generate log tod */
   vtype_todlf,          /* value not used; generate log file datestamp tod */
@@ -615,11 +616,12 @@ static var_entry var_table[] = {
   { "tls_certificate_verified", vtype_int,    &tls_certificate_verified },
   { "tls_cipher",          vtype_stringptr,   &tls_cipher },
   { "tls_peerdn",          vtype_stringptr,   &tls_peerdn },
-#if defined(SUPPORT_TLS) && !defined(USE_GNUTLS)
+#ifdef SUPPORT_TLS
   { "tls_sni",             vtype_stringptr,   &tls_sni },
 #endif
   { "tod_bsdinbox",        vtype_todbsdin,    NULL },
   { "tod_epoch",           vtype_tode,        NULL },
+  { "tod_epoch_l",         vtype_todel,       NULL },
   { "tod_full",            vtype_todf,        NULL },
   { "tod_log",             vtype_todl,        NULL },
   { "tod_logfile",         vtype_todlf,       NULL },
@@ -776,6 +778,7 @@ return rc;
 
 
 
+
 /*************************************************
 *        Pseudo-random number generation         *
 *************************************************/
@@ -788,19 +791,23 @@ weirdness they'll twist this into.  The result should ideally handle fork().
 However, if we're stuck unable to provide this, then we'll fall back to
 appallingly bad randomness.
 
-If SUPPORT_TLS is defined and OpenSSL is used, then this will not be used.
-The GNUTLS randomness functions found do not seem amenable to extracting
-random numbers outside of a TLS context.  Any volunteers?
+If SUPPORT_TLS is defined then this will not be used except as an emergency
+fallback.
 
 Arguments:
   max       range maximum
 Returns     a random number in range [0, max-1]
 */
 
-#if !defined(SUPPORT_TLS) || defined(USE_GNUTLS)
+#ifdef SUPPORT_TLS
+# define vaguely_random_number vaguely_random_number_fallback
+#endif
 int
-pseudo_random_number(int max)
+vaguely_random_number(int max)
 {
+#ifdef SUPPORT_TLS
+# undef vaguely_random_number
+#endif
   static pid_t pid = 0;
   pid_t p2;
 #if defined(HAVE_SRANDOM) && !defined(HAVE_SRANDOMDEV)
@@ -843,7 +850,8 @@ pseudo_random_number(int max)
 #endif
 }
 
-#endif
+
+
 
 /*************************************************
 *             Pick out a name from a string      *
@@ -1519,8 +1527,8 @@ while (last > first)
     domain = Ustrrchr(s, '@');
     if (domain == NULL) return s;
     if (domain - s > sizeof(var_buffer) - 1)
-      log_write(0, LOG_MAIN|LOG_PANIC_DIE, "local part longer than %d in "
-        "string expansion", sizeof(var_buffer));
+      log_write(0, LOG_MAIN|LOG_PANIC_DIE, "local part longer than " SIZE_T_FMT
+          " in string expansion", sizeof(var_buffer));
     Ustrncpy(var_buffer, s, domain - s);
     var_buffer[domain - s] = 0;
     return var_buffer;
@@ -1583,6 +1591,9 @@ while (last > first)
     case vtype_tode:                           /* Unix epoch time of day */
     return tod_stamp(tod_epoch);
 
+    case vtype_todel:                          /* Unix epoch/usec time of day */
+    return tod_stamp(tod_epoch_l);
+
     case vtype_todf:                           /* Full time of day */
     return tod_stamp(tod_full);
 
@@ -1781,7 +1792,7 @@ BOOL tempcond, combined_cond;
 BOOL *subcondptr;
 BOOL sub2_honour_dollar = TRUE;
 int i, rc, cond_type, roffset;
-int64_t num[2];
+int_eximarith_t num[2];
 struct stat statbuf;
 uschar name[256];
 uschar *sub[4];
@@ -3069,14 +3080,14 @@ Returns:      on success: the value of the expression, with *error still NULL
               on failure: an undefined value, with *error = a message
 */
 
-static int64_t eval_op_or(uschar **, BOOL, uschar **);
+static int_eximarith_t eval_op_or(uschar **, BOOL, uschar **);
 
 
-static int64_t
+static int_eximarith_t
 eval_expr(uschar **sptr, BOOL decimal, uschar **error, BOOL endket)
 {
 uschar *s = *sptr;
-int64_t x = eval_op_or(&s, decimal, error);
+int_eximarith_t x = eval_op_or(&s, decimal, error);
 if (*error == NULL)
   {
   if (endket)
@@ -3093,21 +3104,26 @@ return x;
 }
 
 
-static int64_t
+static int_eximarith_t
 eval_number(uschar **sptr, BOOL decimal, uschar **error)
 {
 register int c;
-int64_t n;
+int_eximarith_t n;
 uschar *s = *sptr;
 while (isspace(*s)) s++;
 c = *s;
 if (isdigit(c))
   {
   int count;
-  (void)sscanf(CS s, (decimal? "%lld%n" : "%lli%n"), &n, &count);
+  (void)sscanf(CS s, (decimal? SC_EXIM_DEC "%n" : SC_EXIM_ARITH "%n"), &n, &count);
   s += count;
-  if (tolower(*s) == 'k') { n *= 1024; s++; }
-    else if (tolower(*s) == 'm') { n *= 1024*1024; s++; }
+  switch (tolower(*s))
+    {
+    default: break;
+    case 'k': n *= 1024; s++; break;
+    case 'm': n *= 1024*1024; s++; break;
+    case 'g': n *= 1024*1024*1024; s++; break;
+    }
   while (isspace (*s)) s++;
   }
 else if (c == '(')
@@ -3125,11 +3141,11 @@ return n;
 }
 
 
-static int64_t
+static int_eximarith_t
 eval_op_unary(uschar **sptr, BOOL decimal, uschar **error)
 {
 uschar *s = *sptr;
-int64_t x;
+int_eximarith_t x;
 while (isspace(*s)) s++;
 if (*s == '+' || *s == '-' || *s == '~')
   {
@@ -3147,17 +3163,17 @@ return x;
 }
 
 
-static int64_t
+static int_eximarith_t
 eval_op_mult(uschar **sptr, BOOL decimal, uschar **error)
 {
 uschar *s = *sptr;
-int64_t x = eval_op_unary(&s, decimal, error);
+int_eximarith_t x = eval_op_unary(&s, decimal, error);
 if (*error == NULL)
   {
   while (*s == '*' || *s == '/' || *s == '%')
     {
     int op = *s++;
-    int64_t y = eval_op_unary(&s, decimal, error);
+    int_eximarith_t y = eval_op_unary(&s, decimal, error);
     if (*error != NULL) break;
     /* SIGFPE both on div/mod by zero and on INT_MIN / -1, which would give
      * a value of INT_MAX+1. Note that INT_MIN * -1 gives INT_MIN for me, which
@@ -3180,7 +3196,7 @@ if (*error == NULL)
     if (y == -1 && x == LLONG_MIN && op != '*')
       {
       DEBUG(D_expand)
-        debug_printf("Integer exception dodging: %lld%c-1 coerced to %lld\n",
+        debug_printf("Integer exception dodging: " PR_EXIM_ARITH "%c-1 coerced to " PR_EXIM_ARITH "\n",
             LLONG_MIN, op, LLONG_MAX);
       x = LLONG_MAX;
       continue;
@@ -3207,17 +3223,17 @@ return x;
 }
 
 
-static int64_t
+static int_eximarith_t
 eval_op_sum(uschar **sptr, BOOL decimal, uschar **error)
 {
 uschar *s = *sptr;
-int64_t x = eval_op_mult(&s, decimal, error);
+int_eximarith_t x = eval_op_mult(&s, decimal, error);
 if (*error == NULL)
   {
   while (*s == '+' || *s == '-')
     {
     int op = *s++;
-    int64_t y = eval_op_mult(&s, decimal, error);
+    int_eximarith_t y = eval_op_mult(&s, decimal, error);
     if (*error != NULL) break;
     if (op == '+') x += y; else x -= y;
     }
@@ -3227,16 +3243,16 @@ return x;
 }
 
 
-static int64_t
+static int_eximarith_t
 eval_op_shift(uschar **sptr, BOOL decimal, uschar **error)
 {
 uschar *s = *sptr;
-int64_t x = eval_op_sum(&s, decimal, error);
+int_eximarith_t x = eval_op_sum(&s, decimal, error);
 if (*error == NULL)
   {
   while ((*s == '<' || *s == '>') && s[1] == s[0])
     {
-    int64_t y;
+    int_eximarith_t y;
     int op = *s++;
     s++;
     y = eval_op_sum(&s, decimal, error);
@@ -3249,16 +3265,16 @@ return x;
 }
 
 
-static int64_t
+static int_eximarith_t
 eval_op_and(uschar **sptr, BOOL decimal, uschar **error)
 {
 uschar *s = *sptr;
-int64_t x = eval_op_shift(&s, decimal, error);
+int_eximarith_t x = eval_op_shift(&s, decimal, error);
 if (*error == NULL)
   {
   while (*s == '&')
     {
-    int64_t y;
+    int_eximarith_t y;
     s++;
     y = eval_op_shift(&s, decimal, error);
     if (*error != NULL) break;
@@ -3270,16 +3286,16 @@ return x;
 }
 
 
-static int64_t
+static int_eximarith_t
 eval_op_xor(uschar **sptr, BOOL decimal, uschar **error)
 {
 uschar *s = *sptr;
-int64_t x = eval_op_and(&s, decimal, error);
+int_eximarith_t x = eval_op_and(&s, decimal, error);
 if (*error == NULL)
   {
   while (*s == '^')
     {
-    int64_t y;
+    int_eximarith_t y;
     s++;
     y = eval_op_and(&s, decimal, error);
     if (*error != NULL) break;
@@ -3291,16 +3307,16 @@ return x;
 }
 
 
-static int64_t
+static int_eximarith_t
 eval_op_or(uschar **sptr, BOOL decimal, uschar **error)
 {
 uschar *s = *sptr;
-int64_t x = eval_op_xor(&s, decimal, error);
+int_eximarith_t x = eval_op_xor(&s, decimal, error);
 if (*error == NULL)
   {
   while (*s == '|')
     {
-    int64_t y;
+    int_eximarith_t y;
     s++;
     y = eval_op_xor(&s, decimal, error);
     if (*error != NULL) break;
@@ -5700,7 +5716,7 @@ while (*s != 0)
         {
         uschar *save_sub = sub;
         uschar *error = NULL;
-        int64_t n = eval_expr(&sub, (c == EOP_EVAL10), &error, FALSE);
+        int_eximarith_t n = eval_expr(&sub, (c == EOP_EVAL10), &error, FALSE);
         if (error != NULL)
           {
           expand_string_message = string_sprintf("error in expression "
@@ -5708,7 +5724,7 @@ while (*s != 0)
               save_sub);
           goto EXPAND_FAILED;
           }
-        sprintf(CS var_buffer, "%lld", n);
+        sprintf(CS var_buffer, PR_EXIM_ARITH, n);
         yield = string_cat(yield, &size, &ptr, var_buffer, Ustrlen(var_buffer));
         continue;
         }
@@ -5909,17 +5925,17 @@ while (*s != 0)
         continue;
         }
 
-      /* pseudo-random number less than N */
+      /* vaguely random number less than N */
 
       case EOP_RANDINT:
         {
-        int64_t max;
+        int_eximarith_t max;
         uschar *s;
 
         max = expand_string_integer(sub, TRUE);
         if (expand_string_message != NULL)
           goto EXPAND_FAILED;
-        s = string_sprintf("%d", pseudo_random_number((int)max));
+        s = string_sprintf("%d", vaguely_random_number((int)max));
         yield = string_cat(yield, &size, &ptr, s, Ustrlen(s));
         continue;
         }
@@ -6110,10 +6126,10 @@ Returns:  the integer value, or
           expand_string_message is set NULL for an OK integer
 */
 
-int64_t
+int_eximarith_t
 expand_string_integer(uschar *string, BOOL isplus)
 {
-int64_t value;
+int_eximarith_t value;
 uschar *s = expand_string(string);
 uschar *msg = US"invalid integer \"%s\"";
 uschar *endptr;