+2003-09-21 Hrvoje Niksic <hniksic@xemacs.org>
+
+ * connect.c (select_fd): Change MAXTIME's type to double. Handle
+ its decimal part.
+
+ * retr.c (sleep_between_retrievals): In the random-wait case, use
+ random_float() to wait between 0 and 2*opt.wait seconds.
+
+ * utils.c (run_with_timeout): Accept `double' timeouts. Correctly
+ handle timeout values in (0, 1) range.
+ (random_float): New function.
+
+ * options.h (struct options): Change the types of wait, waitretry,
+ and timeout to double.
+
+ * init.c (cmd_time): Accept floating point time.
+
2003-09-20 Hrvoje Niksic <hniksic@xemacs.org>
* retr.c (get_contents): Cosmetic fixes.
Returns 1 if FD is available, 0 for timeout and -1 for error. */
int
-select_fd (int fd, int maxtime, int writep)
+select_fd (int fd, double maxtime, int writep)
{
fd_set fds;
fd_set *rd = NULL, *wrt = NULL;
FD_SET (fd, &fds);
*(writep ? &wrt : &rd) = &fds;
- tmout.tv_sec = maxtime;
- tmout.tv_usec = 0;
+ tmout.tv_sec = (long)maxtime;
+ tmout.tv_usec = 1000000L * (maxtime - (long)maxtime);
do
result = select (fd + 1, rd, wrt, NULL, &tmout);
void set_connection_host_name PARAMS ((const char *));
int test_socket_open PARAMS ((int));
-int select_fd PARAMS ((int, int, int));
+int select_fd PARAMS ((int, double, int));
uerr_t bindport PARAMS ((unsigned short *, int));
uerr_t acceptport PARAMS ((int *));
void closeport PARAMS ((int));
other than timeout, errno is reset. */
static struct hostent *
-gethostbyname_with_timeout (const char *host_name, int timeout)
+gethostbyname_with_timeout (const char *host_name, double timeout)
{
struct ghbnwt_context ctx;
ctx.host_name = host_name;
static int
getaddrinfo_with_timeout (const char *node, const char *service,
const struct addrinfo *hints, struct addrinfo **res,
- int timeout)
+ double timeout)
{
struct gaiwt_context ctx;
ctx.node = node;
}
#else
{
- struct hostent *hptr = gethostbyname_with_timeout (host, opt.timeout);
+ struct hostent *hptr;
+ hptr = gethostbyname_with_timeout (host, opt.timeout);
if (!hptr)
{
if (!silent)
return 1;
}
-/* Store the value of VAL to *OUT, allowing suffixes for minutes and
- hours. */
+/* Store the value of VAL to *OUT. The value is a time period, by
+ default expressed in seconds. */
+
static int
cmd_time (const char *com, const char *val, void *closure)
{
- long result = 0;
- const char *p = val;
+ double result, mult, divider;
+ int seen_dot, seen_digit;
- /* Search for digits and construct result. */
- for (; *p && ISDIGIT (*p); p++)
- result = (10 * result) + (*p - '0');
- /* If no digits were found, or more than one character is following
- them, bail out. */
- if (p == val || (*p != '\0' && *(p + 1) != '\0'))
+ const char *p;
+ const char *end = val + strlen (val);
+
+ /* Skip trailing whitespace. */
+ while (end > val && ISSPACE (end[-1]))
+ --end;
+
+ if (val == end)
{
- printf (_("%s: Invalid specification `%s'\n"), com, val);
+ err:
+ fprintf (stderr, _("%s: Invalid time specification `%s'\n"), com, val);
return 0;
}
- /* Search for a suffix. */
- switch (TOLOWER (*p))
+
+ switch (TOLOWER (end[-1]))
{
- case '\0':
- /* None */
+ case 's':
+ --end, mult = 1; /* seconds */
break;
case 'm':
- /* Minutes */
- result *= 60;
+ --end, mult = 60; /* minutes */
break;
case 'h':
- /* Seconds */
- result *= 3600;
+ --end, mult = 3600; /* hours */
break;
case 'd':
- /* Days (overflow on 16bit machines) */
- result *= 86400L;
+ --end, mult = 86400; /* days */
break;
case 'w':
- /* Weeks :-) */
- result *= 604800L;
+ --end, mult = 604800; /* weeks */
break;
default:
- printf (_("%s: Invalid specification `%s'\n"), com, val);
- return 0;
+ /* Not a recognized suffix: treat it as part of number, and
+ assume seconds. */
+ mult = 1;
+ }
+
+ /* Skip leading and trailing whitespace. */
+ while (val < end && ISSPACE (*val))
+ ++val;
+ while (val > end && ISSPACE (end[-1]))
+ --end;
+ if (val == end)
+ goto err;
+
+ /* Poor man's strtod: */
+ result = 0;
+ seen_dot = seen_digit = 0;
+ divider = 1;
+
+ p = val;
+ while (p < end)
+ {
+ char ch = *p++;
+ if (ISDIGIT (ch))
+ {
+ if (!seen_dot)
+ result = (10 * result) + (ch - '0');
+ else
+ result += (ch - '0') / (divider *= 10);
+ seen_digit = 1;
+ }
+ else if (ch == '.')
+ {
+ if (!seen_dot)
+ seen_dot = 1;
+ else
+ goto err;
+ }
}
- *(long *)closure = result;
+ if (!seen_digit)
+ goto err;
+ result *= mult;
+ *(double *)closure = result;
return 1;
}
\f
/* Emulation of Unix usleep(). This has a granularity of
milliseconds, but that's ok because:
- a) Wget is only using it with milliseconds;
+ a) Wget is only using it with milliseconds [not anymore, but b)
+ still applies];
b) You can't rely on usleep's granularity anyway. If a caller
expects usleep to respect every microsecond, he's in for a
char *ws_mypath (void);
void ws_help (const char *);
void windows_main_junk (int *, char **, char **);
+int usleep (unsigned long);
#endif /* MSWINDOWS_H */
char *proxy_user; /*oli*/
char *proxy_passwd;
#ifdef HAVE_SELECT
- long timeout; /* The value of read timeout in
- seconds. */
+ double timeout; /* The read/connect/DNS timeout. */
#endif
int random_wait; /* vary from 0 .. wait secs by random()? */
- long wait; /* The wait period between retrievals. */
- long waitretry; /* The wait period between retries. - HEH */
+ double wait; /* The wait period between retrievals. */
+ double waitretry; /* The wait period between retries. - HEH */
int use_robots; /* Do we heed robots.txt? */
long limit_rate; /* Limit the download rate to this
/* Limit the bandwidth by pausing the download for an amount of time.
BYTES is the number of bytes received from the network, and DELTA
- is how long it took to receive them. */
+ is the number of milliseconds it took to receive them. */
static void
limit_bandwidth (long bytes, double delta)
if (count <= opt.waitretry)
sleep (count - 1);
else
- sleep (opt.waitretry);
+ usleep (1000000L * opt.waitretry);
}
else if (opt.wait)
{
/* If random-wait is not specified, or if we are sleeping
between retries of the same download, sleep the fixed
interval. */
- sleep (opt.wait);
+ usleep (1000000L * opt.wait);
else
{
/* Sleep a random amount of time averaging in opt.wait
seconds. The sleeping amount ranges from 0 to
opt.wait*2, inclusive. */
- int waitsecs = random_number (opt.wait * 2 + 1);
-
- DEBUGP (("sleep_between_retrievals: norm=%ld,fuzz=%ld,sleep=%d\n",
- opt.wait, waitsecs - opt.wait, waitsecs));
-
- if (waitsecs)
- sleep (waitsecs);
+ double waitsecs = 2 * opt.wait * random_float ();
+ DEBUGP (("sleep_between_retrievals: avg=%f,sleep=%f\n",
+ opt.wait, waitsecs));
+ usleep (1000000L * waitsecs);
}
}
}
# define VERY_LONG_TYPE unsigned long long
#endif /* use long long */
-/* Defined in cmpt.c: */
+/* These are defined in cmpt.c if missing, therefore it's generally
+ safe to declare their parameters. */
#ifndef HAVE_STRERROR
char *strerror ();
#endif
int vsnprintf ();
#endif
#ifndef HAVE_USLEEP
-int usleep ();
+int usleep PARAMS ((unsigned long));
#endif
#ifndef HAVE_MEMMOVE
void *memmove ();
return (int)bounded;
}
+/* Return a random uniformly distributed floating point number in the
+ [0, 1) range. The precision of returned numbers is 9 digits.
+
+ Modify this to use erand48() where available! */
+
+double
+random_float (void)
+{
+ /* We can't rely on any specific value of RAND_MAX, but I'm pretty
+ sure it's greater than 1000. */
+ int rnd1 = random_number (1000);
+ int rnd2 = random_number (1000);
+ int rnd3 = random_number (1000);
+ return rnd1 / 1000.0 + rnd2 / 1000000.0 + rnd3 / 1000000000.0;
+}
+
#if 0
/* A debugging function for checking whether an MD5 library works. */
#endif /* USE_SIGNAL_TIMEOUT */
int
-run_with_timeout (long timeout, void (*fun) (void *), void *arg)
+run_with_timeout (double timeout, void (*fun) (void *), void *arg)
{
#ifndef USE_SIGNAL_TIMEOUT
fun (arg);
return 0;
}
+ /* Calling alarm() rounds TIMEOUT. If it is smaller than 1, round
+ it to 1, not to 0, because alarm(0) means "never deliver the
+ alarm", i.e. "wait forever", which is not what someone who
+ specifies a 0.5s timeout would expect. */
+ if (timeout < 1)
+ timeout = 1;
+
signal (SIGALRM, abort_run_with_timeout);
if (SETJMP (run_with_timeout_env) != 0)
{
signal (SIGALRM, SIG_DFL);
return 1;
}
- alarm (timeout);
+ alarm ((int) timeout);
fun (arg);
/* Preserve errno in case alarm() or signal() modifies it. */
return 0;
#endif
}
-
int determine_screen_width PARAMS ((void));
int random_number PARAMS ((int));
+double random_float PARAMS ((void));
-int run_with_timeout PARAMS ((long, void (*) (void *), void *));
+int run_with_timeout PARAMS ((double, void (*) (void *), void *));
#endif /* UTILS_H */