X-Git-Url: https://git.exim.org/exim.git/blobdiff_plain/84330b7b581bb93f145706b31288f13408312ccc..870f6ba8a2945754a7f2f66097e3a64465fe1a04:/src/src/expand.c diff --git a/src/src/expand.c b/src/src/expand.c index 4a59c0580..b0c1d5340 100644 --- a/src/src/expand.c +++ b/src/src/expand.c @@ -1,4 +1,4 @@ -/* $Cambridge: exim/src/src/expand.c,v 1.15 2005/03/08 16:57:28 ph10 Exp $ */ +/* $Cambridge: exim/src/src/expand.c,v 1.22 2005/05/23 16:58:56 fanf2 Exp $ */ /************************************************* * Exim - an Internet mail transport agent * @@ -48,6 +48,7 @@ static uschar *expand_string_internal(uschar *, BOOL, uschar **, BOOL); alphabetical order. */ static uschar *item_table[] = { + US"dlfunc", US"extract", US"hash", US"hmac", @@ -55,9 +56,7 @@ static uschar *item_table[] = { US"length", US"lookup", US"nhash", - #ifdef EXIM_PERL - US"perl", - #endif + US"perl", US"readfile", US"readsocket", US"run", @@ -66,6 +65,7 @@ static uschar *item_table[] = { US"tr" }; enum { + EITEM_DLFUNC, EITEM_EXTRACT, EITEM_HASH, EITEM_HMAC, @@ -73,9 +73,7 @@ enum { EITEM_LENGTH, EITEM_LOOKUP, EITEM_NHASH, - #ifdef EXIM_PERL - EITEM_PERL, - #endif + EITEM_PERL, EITEM_READFILE, EITEM_READSOCK, EITEM_RUN, @@ -335,6 +333,7 @@ static var_entry var_table[] = { { "caller_uid", vtype_uid, &real_uid }, { "compile_date", vtype_stringptr, &version_date }, { "compile_number", vtype_stringptr, &version_cnumber }, + { "csa_status", vtype_stringptr, &csa_status }, #ifdef WITH_OLD_DEMIME { "demime_errorlevel", vtype_int, &demime_errorlevel }, { "demime_reason", vtype_stringptr, &demime_reason }, @@ -396,6 +395,7 @@ static var_entry var_table[] = { { "message_body_size", vtype_int, &message_body_size }, { "message_headers", vtype_msgheaders, NULL }, { "message_id", vtype_stringptr, &message_id }, + { "message_linecount", vtype_int, &message_linecount }, { "message_size", vtype_int, &message_size }, #ifdef WITH_CONTENT_SCAN { "mime_anomaly_level", vtype_int, &mime_anomaly_level }, @@ -441,6 +441,7 @@ static var_entry var_table[] = { { "received_count", vtype_int, &received_count }, { "received_for", vtype_stringptr, &received_for }, { "received_protocol", vtype_stringptr, &received_protocol }, + { "received_time", vtype_int, &received_time }, { "recipient_data", vtype_stringptr, &recipient_data }, { "recipient_verify_failure",vtype_stringptr,&recipient_verify_failure }, { "recipients", vtype_recipients, NULL }, @@ -465,6 +466,9 @@ static var_entry var_table[] = { { "sender_host_name", vtype_host_lookup, NULL }, { "sender_host_port", vtype_int, &sender_host_port }, { "sender_ident", vtype_stringptr, &sender_ident }, + { "sender_rate", vtype_stringptr, &sender_rate }, + { "sender_rate_limit", vtype_stringptr, &sender_rate_limit }, + { "sender_rate_period", vtype_stringptr, &sender_rate_period }, { "sender_rcvhost", vtype_stringptr, &sender_rcvhost }, { "sender_verify_failure",vtype_stringptr, &sender_verify_failure }, { "smtp_active_hostname", vtype_stringptr, &smtp_active_hostname }, @@ -1257,6 +1261,7 @@ while (last > first) #ifdef EXPERIMENTAL_DOMAINKEYS case vtype_dk_verify: + if (dk_verify_block == NULL) return US""; s = NULL; if (Ustrcmp(var_table[middle].name, "dk_result") == 0) s = dk_verify_block->result_string; @@ -2332,8 +2337,8 @@ if (yes) /* If this is called from a lookup or an extract, we want to restore $value to what it was at the start of the item, so that it has this value during the -second string expansion. For the call from "if" to this function, save_lookup -is set to lookup_value, so that this statement does nothing. */ +second string expansion. For the call from "if" or "run" to this function, +save_lookup is set to lookup_value, so that this statement does nothing. */ lookup_value = save_lookup; @@ -3071,10 +3076,15 @@ while (*s != 0) or ${perl{sub}{arg1}{arg2}} or up to a maximum of EXIM_PERL_MAX_ARGS arguments (defined below). */ - #ifdef EXIM_PERL #define EXIM_PERL_MAX_ARGS 8 case EITEM_PERL: + #ifndef EXIM_PERL + expand_string_message = US"\"${perl\" encountered, but this facility " + "is not included in this binary"; + goto EXPAND_FAILED; + + #else /* EXIM_PERL */ { uschar *sub_arg[EXIM_PERL_MAX_ARGS + 2]; uschar *new_yield; @@ -3324,7 +3334,6 @@ while (*s != 0) case EITEM_RUN: { FILE *f; - uschar *old_lookup_value = NULL; uschar *arg; uschar **argv; pid_t pid; @@ -3404,18 +3413,17 @@ while (*s != 0) in lookup_value). */ f = fdopen(fd_out, "rb"); - old_lookup_value = lookup_value; lookup_value = NULL; lookup_value = cat_file(f, lookup_value, &lsize, &lptr, NULL); fclose(f); } - /* Process the yes/no strings */ + /* Process the yes/no strings; $value may be useful in both cases */ switch(process_yesno( skipping, /* were previously skipping */ runrc == 0, /* success/failure indicator */ - old_lookup_value, /* value to reset for string2 */ + lookup_value, /* value to reset for string2 */ &s, /* input pointer */ &yield, /* output pointer */ &size, /* output size */ @@ -3846,6 +3854,106 @@ while (*s != 0) continue; } + + + /* If ${dlfunc support is configured, handle calling dynamically-loaded + functions, unless locked out at this time. Syntax is ${dlfunc{file}{func}} + or ${dlfunc{file}{func}{arg}} or ${dlfunc{file}{func}{arg1}{arg2}} or up to + a maximum of EXPAND_DLFUNC_MAX_ARGS arguments (defined below). */ + + #define EXPAND_DLFUNC_MAX_ARGS 8 + + case EITEM_DLFUNC: + #ifndef EXPAND_DLFUNC + expand_string_message = US"\"${dlfunc\" encountered, but this facility " + "is not included in this binary"; + goto EXPAND_FAILED; + + #else /* EXPAND_DLFUNC */ + { + tree_node *t; + exim_dlfunc_t *func; + uschar *result; + int status, argc; + uschar *argv[EXPAND_DLFUNC_MAX_ARGS + 3]; + + if ((expand_forbid & RDO_DLFUNC) != 0) + { + expand_string_message = + US"dynamically-loaded functions are not permitted"; + goto EXPAND_FAILED; + } + + switch(read_subs(argv, EXPAND_DLFUNC_MAX_ARGS + 2, 2, &s, skipping, + TRUE, US"dlfunc")) + { + case 1: goto EXPAND_FAILED_CURLY; + case 2: + case 3: goto EXPAND_FAILED; + } + + /* If skipping, we don't actually do anything */ + + if (skipping) continue; + + /* Look up the dynamically loaded object handle in the tree. If it isn't + found, dlopen() the file and put the handle in the tree for next time. */ + + t = tree_search(dlobj_anchor, argv[0]); + if (t == NULL) + { + void *handle = dlopen(CS argv[0], RTLD_LAZY); + if (handle == NULL) + { + expand_string_message = string_sprintf("dlopen \"%s\" failed: %s", + argv[0], dlerror()); + log_write(0, LOG_MAIN|LOG_PANIC, "%s", expand_string_message); + goto EXPAND_FAILED; + } + t = store_get_perm(sizeof(tree_node) + Ustrlen(argv[0])); + Ustrcpy(t->name, argv[0]); + t->data.ptr = handle; + (void)tree_insertnode(&dlobj_anchor, t); + } + + /* Having obtained the dynamically loaded object handle, look up the + function pointer. */ + + func = (exim_dlfunc_t *)dlsym(t->data.ptr, CS argv[1]); + if (func == NULL) + { + expand_string_message = string_sprintf("dlsym \"%s\" in \"%s\" failed: " + "%s", argv[1], argv[0], dlerror()); + log_write(0, LOG_MAIN|LOG_PANIC, "%s", expand_string_message); + goto EXPAND_FAILED; + } + + /* Call the function and work out what to do with the result. If it + returns OK, we have a replacement string; if it returns DEFER then + expansion has failed in a non-forced manner; if it returns FAIL then + failure was forced; if it returns ERROR or any other value there's a + problem, so panic slightly. */ + + result = NULL; + for (argc = 0; argv[argc] != NULL; argc++); + status = func(&result, argc - 2, &argv[2]); + if(status == OK) + { + if (result == NULL) result = US""; + yield = string_cat(yield, &size, &ptr, result, Ustrlen(result)); + continue; + } + else + { + expand_string_message = result == NULL ? US"(no message)" : result; + if(status == FAIL_FORCED) expand_string_forcedfail = TRUE; + else if(status != FAIL) + log_write(0, LOG_MAIN|LOG_PANIC, "dlfunc{%s}{%s} failed (%d): %s", + argv[0], argv[1], status, expand_string_message); + goto EXPAND_FAILED; + } + } + #endif /* EXPAND_DLFUNC */ } /* Control reaches here if the name is not recognized as one of the more