2
0
mirror of https://github.com/vdukhovni/postfix synced 2025-08-30 13:48:06 +00:00

snapshot-20010204

This commit is contained in:
Wietse Venema
2001-02-04 00:00:00 -05:00
committed by Viktor Dukhovni
parent dd6c4450bb
commit edac954e0e
34 changed files with 241 additions and 55 deletions

1
postfix/.indent.pro vendored
View File

@@ -27,6 +27,7 @@
-TDICT_ENV
-TDICT_HT
-TDICT_LDAP
-TDICT_DEBUG
-TDICT_MYSQL
-TDICT_NI
-TDICT_NIS

View File

@@ -18,8 +18,21 @@ from or to the loopback interface:
You can specify one or more hosts, domains, addresses or net/masks.
3 - Making daemon programs more verbose
=======================================
2b - Record the SMTP connection with a sniffer
==============================================
This example uses tcpdump. In order to record a conversation you
need to specify a large enough buffer or else you will miss some
or all of the packet payload.
tcpdump -w /file/name -s 2000 host hostname and port 25
Run this for a while, stop with Ctrl-C when done. To view the data
use a binary viewer, or use my tcpdumpx utility that is available
from ftp://ftp.porcupine.org/pub/debugging.
3 - Making Postfix daemon programs more verbose
===============================================
Append one or more -v options to selected daemon definitions in
/etc/postfix/master.cf and type "postfix reload". This will cause

View File

@@ -4831,13 +4831,6 @@ Apologies for any names omitted.
bug that causes mail delivery problems when "." and "CRLF"
arrive in separate packets. File: html/faq.html.
20010131
The code that reports a DNS lookup error now includes the
record type that was being looked up, so that people will
not misinterpret an MX lookup problem as an A record lookup
problem. File: dns/dns_lookup.c.
20010201
Bugfix: another missing initialization in the mysql client.
@@ -4860,3 +4853,19 @@ Apologies for any names omitted.
Feature: disable mailbox size limits for the local and
virtual delivery agents by setting mailbox_size_limit or
virtual_mailbox_limit to zero.
20010203
Update: null candidate patch from Patrick Rak. Files:
nqmgr/qmgr_entry.c nqmgr/qmgr_job.c nqmgr/qmgr_message.c.
Cleanup: added one gruesome command to the postlink script
for hyperlinking nroff manual page output. Word abbreviation
broke some <a href...> </a> instances across line boundaries.
sed(1) is an amazing tool. File: mantools/postlink.
20010204
Laid the ground work for logging of table accesses. This
will give more insight into how Postfix uses its lookup
tables. User interface comes later. File: util/dict_debug.c.

View File

@@ -16,8 +16,8 @@ ERROR(8) ERROR(8)
requests from the queue manager. Each request specifies a
queue file, a sender address, a domain or host name that
is treated as the reason for non-delivery, and recipient
information. This program expects to be run from the <a href="master.8.html"><b>mas-</b>
<b>ter</b>(8)</a> process manager.
information. This program expects to be run from the <a href="master.8.html"><b>mas-</b></a>
<a href="master.8.html"><b>ter</b>(8)</a> process manager.
The error mailer client forces all recipients to bounce,
using the domain or host information as the reason for

View File

@@ -16,8 +16,8 @@ LOCAL(8) LOCAL(8)
Postfix queue manager to deliver mail to local recipients.
Each delivery request specifies a queue file, a sender
address, a domain or host to deliver to, and one or more
recipients. This program expects to be run from the <a href="master.8.html"><b>mas-</b>
<b>ter</b>(8)</a> process manager.
recipients. This program expects to be run from the <a href="master.8.html"><b>mas-</b></a>
<a href="master.8.html"><b>ter</b>(8)</a> process manager.
The <b>local</b> daemon updates queue files and marks recipients
as finished, or it informs the queue manager that delivery

View File

@@ -14,8 +14,8 @@ NQMGR(8) NQMGR(8)
<b>DESCRIPTION</b>
The <b>nqmgr</b> daemon awaits the arrival of incoming mail and
arranges for its delivery via Postfix delivery processes.
The actual mail routing strategy is delegated to the <a href="trivial-rewrite.8.html"><b>triv-</b>
<b>ial-rewrite</b>(8)</a> daemon. This program expects to be run
The actual mail routing strategy is delegated to the <a href="trivial-rewrite.8.html"><b>triv-</b></a>
<a href="trivial-rewrite.8.html"><b>ial-rewrite</b>(8)</a> daemon. This program expects to be run
from the <a href="master.8.html"><b>master</b>(8)</a> process manager.
Mail addressed to the local <b>double-bounce</b> address is

View File

@@ -19,8 +19,8 @@ POSTDROP(1) POSTDROP(1)
and with group write permission to the <b>maildrop</b> queue
directory.
The <b>postdrop</b> command is automatically invoked by the <a href="sendmail.1.html"><b>send-</b>
<b>mail</b>(1)</a> mail posting agent when the <b>maildrop</b> queue direc-
The <b>postdrop</b> command is automatically invoked by the <a href="sendmail.1.html"><b>send-</b></a>
<a href="sendmail.1.html"><b>mail</b>(1)</a> mail posting agent when the <b>maildrop</b> queue direc-
tory is not world-writable.
Options:

View File

@@ -14,8 +14,8 @@ QMGR(8) QMGR(8)
<b>DESCRIPTION</b>
The <b>qmgr</b> daemon awaits the arrival of incoming mail and
arranges for its delivery via Postfix delivery processes.
The actual mail routing strategy is delegated to the <a href="trivial-rewrite.8.html"><b>triv-</b>
<b>ial-rewrite</b>(8)</a> daemon. This program expects to be run
The actual mail routing strategy is delegated to the <a href="trivial-rewrite.8.html"><b>triv-</b></a>
<a href="trivial-rewrite.8.html"><b>ial-rewrite</b>(8)</a> daemon. This program expects to be run
from the <a href="master.8.html"><b>master</b>(8)</a> process manager.
Mail addressed to the local <b>double-bounce</b> address is

View File

@@ -43,8 +43,8 @@ TRIVIAL-REWRITE(8) TRIVIAL-REWRITE(8)
The <b>trivial-rewrite</b> daemon by default only distin-
guishes between local and non-local mail. For finer
control over mail routing, use the optional <a href="transport.5.html"><b>trans-</b>
<b>port</b>(5)</a> lookup table.
control over mail routing, use the optional <a href="transport.5.html"><b>trans-</b></a>
<a href="transport.5.html"><b>port</b>(5)</a> lookup table.
This program expects to be run from the <a href="master.8.html"><b>master</b>(8)</a> process
manager.

View File

@@ -979,7 +979,7 @@ appear as part of a client hostname/address restriction list.
<dt>Default:
<dd><b>maps_rbl_domains = rbl.maps.vix.com, dul.maps.vix.com</b>
<dd><b>maps_rbl_domains = blackholes.mail-abuse.org</b>
<p>

View File

@@ -46,5 +46,6 @@ exec sed '
s/[<bB>]*trans[-</bB>]*\n*[ <bB>]*port[</bB>]*(5)/<a href="transport.5.html">&<\/a>/
s/[<bB>]*virtual[</bB>]*(5)/<a href="virtual.5.html">&<\/a>/
s/[<bB>]*virtual[</bB>]*(8)/<a href="virtual.8.html">&<\/a>/
s/\(<a href="[^"]*">\)\([<bB>]*[a-z0-9-]*[-</bB>]*\)\(\n *\)\([<bB>]*[a-z0-9-]*[</bB>]*([0-9])\)\(<\/a>\)/\1\2\5\3\1\4\5/
s/RFC *\([0-9]*\)/<a href="http:\/\/www.faqs.org\/rfcs\/rfc\1.html">&<\/a>/
' "$@"

View File

@@ -168,8 +168,8 @@ static int dns_query(const char *name, int type, int flags,
len = res_search((char *) name, C_IN, type, reply->buf, sizeof(reply->buf));
if (len < 0) {
if (why)
vstring_sprintf(why, "Name service error for %s (%s) while looking up the %s record.",
name, dns_strerror(h_errno), dns_strtype(type));
vstring_sprintf(why, "Name service error for %s: %s",
name, dns_strerror(h_errno));
if (msg_verbose)
msg_info("dns_query: %s (%s): %s",
name, dns_strtype(type), dns_strerror(h_errno));

View File

@@ -15,7 +15,7 @@
* Version of this program.
*/
#define VAR_MAIL_VERSION "mail_version"
#define DEF_MAIL_VERSION "Snapshot-20010202"
#define DEF_MAIL_VERSION "Snapshot-20010204"
extern char *var_mail_version;
/* LICENSE

View File

@@ -193,6 +193,10 @@ void qmgr_entry_done(QMGR_ENTRY *entry, int which)
* the queue is not marked as a blocker anymore, with extra handling of
* queues which were declared dead.
*
* Note that changing the blocker status also affects the candidate cache.
* Most of the cases would be automatically recognized by the current job
* change, but we play safe and reset the cache explicitly below.
*
* Keeping the transport blocker tag odd is an easy way to make sure the tag
* never matches jobs that are not explicitly marked as blockers.
*/
@@ -200,6 +204,7 @@ void qmgr_entry_done(QMGR_ENTRY *entry, int which)
if (queue->window > queue->busy_refcount && queue->todo.next != 0) {
transport->blocker_tag += 2;
transport->job_current = transport->job_list.next;
transport->candidate_cache_current = 0;
}
if (queue->window > queue->busy_refcount || queue->window == 0)
queue->blocker_tag = 0;

View File

@@ -489,11 +489,17 @@ static QMGR_JOB *qmgr_job_candidate(QMGR_JOB *current)
* Fetch the result directly from the cache if the cache is still valid.
*
* Note that we cache negative results too, so the cache must be invalidated
* by resetting the cache time or current job pointer, not the candidate
* pointer itself.
* by resetting the cached current job pointer, not the candidate pointer
* itself.
*
* In case the cache is valid and contains no candidate, we can ignore the
* time change, as it affects only which candidate is the best, not if
* one exists. However, this feature requires that we no longer relax the
* cache resetting rules, depending on the automatic cache timeout.
*/
if (transport->candidate_cache_current == current
&& transport->candidate_cache_time == now)
&& (transport->candidate_cache_time == now
|| transport->candidate_cache == 0))
return (transport->candidate_cache);
/*
@@ -726,19 +732,25 @@ static void qmgr_job_pop(QMGR_JOB *job)
*/
job->stack_level = 0;
/*
* Explicitely reset the candidate cache. It's not worth trying to skip
* this under some complicated conditions - in most cases the popped job
* is the current job so we would have to reset it anyway.
*/
RESET_CANDIDATE_CACHE(transport);
/*
* Here we leave the remaining work involving the proper placement on the
* job list to the caller. The most important reason for this is that it
* allows us not to look up where exactly to place the job.
*
* The caller is also made responsible for invalidating the candidate and
* current job caches if necessary.
* The caller is also made responsible for invalidating the current job
* cache if necessary.
*/
#if 0
QMGR_LIST_UNLINK(transport->job_list, QMGR_JOB *, job, transport_peers);
QMGR_LIST_LINK(transport->job_list, some_prev, job, some_next, transport_peers);
RESET_CANDIDATE_CACHE(transport);
if (transport->job_current == job)
transport->job_current = job->transport_peers.next;
#endif

View File

@@ -848,11 +848,10 @@ static void qmgr_message_assign(QMGR_MESSAGE *message)
/*
* Note that even if qmgr_job_obtain() reset the job candidate cache of
* all transports to which we assigned new recipients, this message may
* have other jobs which we didn't touch at all this time. But as the
* number of unread recipients affecting the candidate selection might
* have changed considerably, let's invalidate the caches if it seems it
* might be of some use. It's not critical though because the cache will
* expire within one second anyway.
* have other jobs which we didn't touch at all this time. But the number
* of unread recipients affecting the candidate selection might have
* changed considerably, so we must invalidate the caches if it might be
* of some use.
*/
for (job = message->job_list.next; job; job = job->message_peers.next)
if (job->selected_entries < job->read_entries

View File

@@ -338,7 +338,7 @@ DNS_RR *smtp_domain_addr(char *name, VSTRING *why, int *found_myself)
dns_rr_free(mx_names);
if (addr_list == 0) {
smtp_errno = SMTP_RETRY;
msg_warn("MX hosts for %s have no valid A record", name);
msg_warn("no MX host for %s has a valid A record", name);
break;
}
best_found = (addr_list ? addr_list->pref : IMPOSSIBLE_PREFERENCE);

View File

@@ -22,7 +22,7 @@ SRCS = argv.c argv_split.c attr.c basename.c binhash.c chroot_uid.c \
stream_connect.c stream_trigger.c dict_regexp.c mac_expand.c \
clean_env.c watchdog.c spawn_command.c duplex_pipe.c sane_rename.c \
sane_link.c unescape.c timed_read.c timed_write.c dict_tcp.c \
hex_quote.c dict_alloc.c rand_sleep.c sane_time.c
hex_quote.c dict_alloc.c rand_sleep.c sane_time.c dict_debug.c
OBJS = argv.o argv_split.o attr.o basename.o binhash.o chroot_uid.o \
close_on_exec.o concatenate.o dict.o dict_db.o dict_dbm.o \
dict_env.o dict_ht.o dict_ldap.o dict_mysql.o dict_ni.o dict_nis.o \
@@ -46,7 +46,7 @@ OBJS = argv.o argv_split.o attr.o basename.o binhash.o chroot_uid.o \
stream_connect.o stream_trigger.o dict_regexp.o mac_expand.o \
clean_env.o watchdog.o spawn_command.o duplex_pipe.o sane_rename.o \
sane_link.o unescape.o timed_read.o timed_write.o dict_tcp.o \
hex_quote.o dict_alloc.o rand_sleep.o sane_time.o
hex_quote.o dict_alloc.o rand_sleep.o sane_time.o dict_debug.o
HDRS = argv.h attr.h binhash.h chroot_uid.h connect.h dict.h dict_db.h \
dict_dbm.h dict_env.h dict_ht.h dict_ldap.h dict_mysql.h \
dict_ni.h dict_nis.h dict_nisplus.h dir_forest.h events.h \
@@ -402,6 +402,14 @@ dict_db.o: argv.h
dict_db.o: dict_db.h
dict_dbm.o: dict_dbm.c
dict_dbm.o: sys_defs.h
dict_debug.o: dict_debug.c
dict_debug.o: sys_defs.h
dict_debug.o: msg.h
dict_debug.o: mymalloc.h
dict_debug.o: dict.h
dict_debug.o: vstream.h
dict_debug.o: vbuf.h
dict_debug.o: argv.h
dict_env.o: dict_env.c
dict_env.o: sys_defs.h
dict_env.o: mymalloc.h

View File

@@ -109,7 +109,7 @@
/* dict_sequence() steps throuh the named dictionary and returns
/* keys and values in some implementation-defined order. The func
/* argument is DICT_SEQ_FUN_FIRST to set the cursor to the first
/* entry or DICT_SEQ_FUN_NEXT so select the next entry. The result
/* entry or DICT_SEQ_FUN_NEXT to select the next entry. The result
/* is owned by the underlying dictionary method. Make a copy if the
/* result is to be modified, or if the result is to survive multiple
/* dict_sequence() calls.

View File

@@ -42,6 +42,9 @@ typedef struct DICT {
extern DICT *dict_alloc(const char *, const char *, int);
extern void dict_free(DICT *);
extern DICT *dict_debug(DICT *);
#define DICT_DEBUG(d) ((d)->flags & DICT_FLAG_DEBUG ? dict_debug(d) : (d))
#define DICT_FLAG_DUP_WARN (1<<0) /* if file, warn about dups */
#define DICT_FLAG_DUP_IGNORE (1<<1) /* if file, ignore dups */
#define DICT_FLAG_TRY0NULL (1<<2) /* do not append 0 to key/value */
@@ -51,6 +54,7 @@ extern void dict_free(DICT *);
#define DICT_FLAG_LOCK (1<<6) /* lock before access */
#define DICT_FLAG_DUP_REPLACE (1<<7) /* if file, replace dups */
#define DICT_FLAG_SYNC_UPDATE (1<<8) /* if file, sync updates */
#define DICT_FLAG_DEBUG (1<<9) /* log access */
extern int dict_unknown_allowed;
extern int dict_errno;

View File

@@ -523,7 +523,7 @@ static DICT *dict_db_open(const char *class, const char *path, int open_flags,
dict_db->dict.flags |= (DICT_FLAG_TRY1NULL | DICT_FLAG_TRY0NULL);
dict_db->db = db;
myfree(db_path);
return (&dict_db->dict);
return (DICT_DEBUG(&dict_db->dict));
}
/* dict_hash_open - create association with data base */

View File

@@ -409,7 +409,7 @@ DICT *dict_dbm_open(const char *path, int open_flags, int dict_flags)
dict_dbm->dict.flags |= (DICT_FLAG_TRY0NULL | DICT_FLAG_TRY1NULL);
dict_dbm->dbm = dbm;
return (&dict_dbm->dict);
return (DICT_DEBUG(&dict_dbm->dict));
}
#endif

View File

@@ -0,0 +1,134 @@
/*++
/* NAME
/* dict_debug 3
/* SUMMARY
/* dictionary manager, logging proxy
/* SYNOPSIS
/* #include <dict.h>
/*
/* DICT *dict_debug(dict_handle)
/* DICT *dict_handle;
/*
/* DICT *DICT_DEBUG(dict_handle)
/* DICT *dict_handle;
/* DESCRIPTION
/* dict_debug() encapsulates the given dictionary object and returns
/* a proxy object that logs all access to the encapsulated object.
/* This is more convenient than having to add logging capability
/* to each individual dictionary access method.
/*
/* DICT_DEBUG() is an unsafe macro that returns the original object if
/* the object's debugging flag is not set, and that otherwise encapsulates
/* the object with dict_debug(). This macro simplifies usage by avoiding
/* clumsy expressions. The macro evaluates its argument multiple times.
/* DIAGNOSTICS
/* Fatal errors: out of memory.
/* LICENSE
/* .ad
/* .fi
/* The Secure Mailer license must be distributed with this software.
/* AUTHOR(S)
/* Wietse Venema
/* IBM T.J. Watson Research
/* P.O. Box 704
/* Yorktown Heights, NY 10598, USA
/*--*/
/* System libraries. */
#include <sys_defs.h>
/* Utility library. */
#include <msg.h>
#include <mymalloc.h>
#include <dict.h>
/* Application-specific. */
typedef struct {
DICT dict; /* the proxy service */
DICT *real_dict; /* encapsulated object */
} DICT_DEBUG;
/* dict_debug_lookup - log lookup operation */
static const char *dict_debug_lookup(DICT *dict, const char *key)
{
DICT_DEBUG *dict_debug = (DICT_DEBUG *) dict;
const char *result;
result = dict_get(dict_debug->real_dict, key);
msg_info("%s:%s lookup: \"%s\" = \"%s\"", dict->type, dict->name, key,
result ? result : dict_errno ? "try again" : "not_found");
return (result);
}
/* dict_debug_update - log update operation */
static void dict_debug_update(DICT *dict, const char *key, const char *value)
{
DICT_DEBUG *dict_debug = (DICT_DEBUG *) dict;
msg_info("%s:%s update: \"%s\" = \"%s\"", dict->type, dict->name,
key, value);
dict_put(dict_debug->real_dict, key, value);
}
/* dict_debug_delete - log delete operation */
static int dict_debug_delete(DICT *dict, const char *key)
{
DICT_DEBUG *dict_debug = (DICT_DEBUG *) dict;
int result;
result = dict_del(dict_debug->real_dict, key);
msg_info("%s:%s delete: \"%s\" = \"%s\"", dict->type, dict->name, key,
result ? "failed" : "success");
return (result);
}
/* dict_debug_sequence - log sequence operation */
static int dict_debug_sequence(DICT *dict, int function,
const char **key, const char **value)
{
DICT_DEBUG *dict_debug = (DICT_DEBUG *) dict;
int result;
result = dict_seq(dict_debug->real_dict, function, key, value);
if (result == 0)
msg_info("%s:%s sequence: \"%s\" = \"%s\"", dict->type, dict->name,
*key, *value);
else
msg_info("%s:%s sequence: found EOF", dict->type, dict->name);
return (result);
}
/* dict_debug_close - log operation */
static void dict_debug_close(DICT *dict)
{
DICT_DEBUG *dict_debug = (DICT_DEBUG *) dict;
dict_close(dict_debug->real_dict);
dict_free(dict);
}
/* dict_debug - encapsulate dictionary object and install proxies */
DICT *dict_debug(DICT *real_dict)
{
DICT_DEBUG *dict_debug;
dict_debug = (DICT_DEBUG *) dict_alloc(real_dict->type,
real_dict->name, sizeof(*dict_debug));
dict_debug->dict.flags = real_dict->flags; /* XXX not synchronized */
dict_debug->dict.lookup = dict_debug_lookup;
dict_debug->dict.update = dict_debug_update;
dict_debug->dict.delete = dict_debug_delete;
dict_debug->dict.sequence = dict_debug_sequence;
dict_debug->dict.close = dict_debug_close;
dict_debug->real_dict = real_dict;
return (&dict_debug->dict);
}

View File

@@ -80,5 +80,5 @@ DICT *dict_env_open(const char *name, int unused_flags, int dict_flags)
dict->update = dict_env_update;
dict->close = dict_env_close;
dict->flags = dict_flags | DICT_FLAG_FIXED;
return (dict);
return (DICT_DEBUG(dict));
}

View File

@@ -842,7 +842,7 @@ DICT *dict_ldap_open(const char *ldapsource, int dummy, int dict_flags)
/*
* Otherwise, we're all set. Return the new dict_ldap structure.
*/
return (&dict_ldap->dict);
return (DICT_DEBUG(&dict_ldap->dict));
}
#endif

View File

@@ -360,7 +360,7 @@ DICT *dict_mysql_open(const char *name, int unused_open_flags, int dict_flags)
if (dict_mysql->pldb == NULL)
msg_fatal("couldn't intialize pldb!\n");
dict_register(name, (DICT *) dict_mysql);
return &dict_mysql->dict;
return (DICT_DEBUG(&dict_mysql->dict));
}
/* mysqlname_parse - parse mysql configuration file */

View File

@@ -174,7 +174,7 @@ DICT *dict_ni_open(const char *path, int unused_flags, int dict_flags)
d->dict.close = dict_ni_close;
d->dict.flags = dict_flags | DICT_FLAG_FIXED;
return &d->dict;
return (DICT_DEBUG(&d->dict));
}
#endif

View File

@@ -216,7 +216,7 @@ DICT *dict_nis_open(const char *map, int unused_flags, int dict_flags)
dict_nis->dict.flags |= (DICT_FLAG_TRY1NULL | DICT_FLAG_TRY0NULL);
if (dict_nis_domain == 0)
dict_nis_init();
return (&dict_nis->dict);
return (DICT_DEBUG(&dict_nis->dict));
}
#endif

View File

@@ -65,5 +65,5 @@ DICT *dict_nisplus_open(const char *map, int unused_flags, int dict_flags)
sizeof(*dict_nisplus));
dict_nisplus->dict.close = dict_nisplus_close;
dict_nisplus->dict.flags = dict_flags | DICT_FLAG_FIXED;
return (&dict_nisplus->dict);
return (DICT_DEBUG(&dict_nisplus->dict));
}

View File

@@ -364,7 +364,7 @@ DICT *dict_pcre_open(const char *map, int unused_flags, int dict_flags)
vstring_free(line_buffer);
vstream_fclose(map_fp);
return (&dict_pcre->dict);
return (DICT_DEBUG(&dict_pcre->dict));
}
#endif /* HAS_PCRE */

View File

@@ -386,7 +386,7 @@ DICT *dict_regexp_open(const char *map, int unused_flags, int dict_flags)
vstring_free(line_buffer);
vstream_fclose(map_fp);
return (&dict_regexp->dict);
return (DICT_DEBUG(&dict_regexp->dict));
}
#endif

View File

@@ -268,5 +268,5 @@ DICT *dict_tcp_open(const char *map, int unused_flags, int dict_flags)
dict_tcp->dict.lookup = dict_tcp_lookup;
dict_tcp->dict.close = dict_tcp_close;
dict_tcp->dict.flags = dict_flags | DICT_FLAG_FIXED;
return (&dict_tcp->dict);
return (DICT_DEBUG(&dict_tcp->dict));
}

View File

@@ -146,5 +146,5 @@ DICT *dict_unix_open(const char *map, int unused_flags, int dict_flags)
dict_unix->dict.lookup = lp->lookup;
dict_unix->dict.close = dict_unix_close;
dict_unix->dict.flags = dict_flags | DICT_FLAG_FIXED;
return (&dict_unix->dict);
return (DICT_DEBUG(&dict_unix->dict));
}

View File

@@ -11,7 +11,7 @@
/* unsigned variation;
/* DESCRIPTION
/* rand_sleep() blocks the current process for an amount of time
/* pseudo-randomly chosen from the interval (delay += variation/2).
/* pseudo-randomly chosen from the interval (delay +- variation/2).
/*
/* Arguments:
/* .IP delay