/* Various functions of utilitarian nature.
- Copyright (C) 1995, 1996, 1997, 1998, 2000 Free Software Foundation, Inc.
+ Copyright (C) 1995, 1996, 1997, 1998, 2000, 2001
+ Free Software Foundation, Inc.
-This file is part of Wget.
+This file is part of GNU Wget.
-This program is free software; you can redistribute it and/or modify
+GNU Wget is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-This program is distributed in the hope that it will be useful,
+GNU Wget is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
+along with Wget; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#include <config.h>
ptm->tm_hour, ptm->tm_min, ptm->tm_sec);
return output;
}
-
-/* Returns an error message for ERRNUM. #### This requires more work.
- This function, as well as the whole error system, is very
- ill-conceived. */
-const char *
-uerrmsg (uerr_t errnum)
-{
- switch (errnum)
- {
- case URLUNKNOWN:
- return _("Unknown/unsupported protocol");
- break;
- case URLBADPORT:
- return _("Invalid port specification");
- break;
- case URLBADHOST:
- return _("Invalid host name");
- break;
- default:
- abort ();
- /* $@#@#$ compiler. */
- return NULL;
- }
-}
\f
/* The Windows versions of the following two functions are defined in
mswindows.c. */
-/* A cuserid() immitation using getpwuid(), to avoid hassling with
- utmp. Besides, not all systems have cuesrid(). Under Windows, it
- is defined in mswindows.c.
-
- If WHERE is non-NULL, the username will be stored there.
- Otherwise, it will be returned as a static buffer (as returned by
- getpwuid()). In the latter case, the buffer should be copied
- before calling getpwuid() or pwd_cuserid() again. */
#ifndef WINDOWS
-char *
-pwd_cuserid (char *where)
-{
- struct passwd *pwd;
-
- if (!(pwd = getpwuid (getuid ())) || !pwd->pw_name)
- return NULL;
- if (where)
- {
- strcpy (where, pwd->pw_name);
- return where;
- }
- else
- return pwd->pw_name;
-}
-
void
fork_to_background (void)
{
}
#endif /* not WINDOWS */
\f
+char *
+ps (char *orig)
+{
+ char *r = xstrdup (orig);
+ path_simplify (r);
+ return r;
+}
+
/* Canonicalize PATH, and return a new path. The new path differs from PATH
in that:
Multple `/'s are collapsed to a single `/'.
Always use '/' as stub_char.
Don't check for local things using canon_stat.
Change the original string instead of strdup-ing.
- React correctly when beginning with `./' and `../'. */
+ React correctly when beginning with `./' and `../'.
+ Don't zip out trailing slashes. */
void
path_simplify (char *path)
{
i = start + 1;
}
- /* Check for trailing `/'. */
- if (start && !path[i])
- {
- zero_last:
- path[--i] = '\0';
- break;
- }
-
/* Check for `../', `./' or trailing `.' by itself. */
if (path[i] == '.')
{
/* Handle trailing `.' by itself. */
if (!path[i + 1])
- goto zero_last;
+ {
+ path[--i] = '\0';
+ break;
+ }
/* Handle `./'. */
if (path[i + 1] == '/')
}
} /* path == '.' */
} /* while */
-
- if (!*path)
- {
- *path = stub_char;
- path[1] = '\0';
- }
}
\f
/* "Touch" FILE, i.e. make its atime and mtime equal to the time
}
return 0;
}
+
+/* Merge BASE with FILE. BASE can be a directory or a file name, FILE
+ should be a file name. For example, file_merge("/foo/bar", "baz")
+ will return "/foo/baz". file_merge("/foo/bar/", "baz") will return
+ "foo/bar/baz".
+
+ In other words, it's a simpler and gentler version of uri_merge_1. */
+
+char *
+file_merge (const char *base, const char *file)
+{
+ char *result;
+ const char *cut = (const char *)strrchr (base, '/');
+
+ if (!cut)
+ cut = base + strlen (base);
+
+ result = (char *)xmalloc (cut - base + 1 + strlen (file) + 1);
+ memcpy (result, base, cut - base);
+ result[cut - base] = '/';
+ strcpy (result + (cut - base) + 1, file);
+
+ return result;
+}
\f
static int in_acclist PARAMS ((const char *const *, const char *, int));
/* First check whether the set element already exists. If it does,
do nothing so that we don't have to free() the old element and
then strdup() a new one. */
- if (hash_table_exists (ht, s))
+ if (hash_table_contains (ht, s))
return;
/* We use "1" as value. It provides us a useful and clear arbitrary
hash_table_put (ht, xstrdup (s), "1");
}
-/* Synonym for hash_table_exists... */
+/* Synonym for hash_table_contains... */
int
-string_set_exists (struct hash_table *ht, const char *s)
+string_set_contains (struct hash_table *ht, const char *s)
{
- return hash_table_exists (ht, s);
+ return hash_table_contains (ht, s);
}
static int
bytes are sufficient. Using more might be a good idea.
This function does not go through the hoops that long_to_string
- goes to because it doesn't need to be fast. (It's called perhaps
+ goes to because it doesn't aspire to be fast. (It's called perhaps
once in a Wget run.) */
static void
{
int res = 1;
if (a < 0)
- a = -a;
+ {
+ a = -a;
+ ++res;
+ }
while ((a /= 10) != 0)
++res;
return res;
}
#define ONE_DIGIT(figure) *p++ = n / (figure) + '0'
-
-#define DIGITS_1(figure) \
- ONE_DIGIT (figure)
-#define DIGITS_2(figure) \
- (ONE_DIGIT (figure), n %= (figure)); \
- DIGITS_1 ((figure) / 10)
-#define DIGITS_3(figure) \
- (ONE_DIGIT (figure), n %= (figure)); \
- DIGITS_2 ((figure) / 10)
-#define DIGITS_4(figure) \
- (ONE_DIGIT (figure), n %= (figure)); \
- DIGITS_3 ((figure) / 10)
-#define DIGITS_5(figure) \
- (ONE_DIGIT (figure), n %= (figure)); \
- DIGITS_4 ((figure) / 10)
-#define DIGITS_6(figure) \
- (ONE_DIGIT (figure), n %= (figure)); \
- DIGITS_5 ((figure) / 10)
-#define DIGITS_7(figure) \
- (ONE_DIGIT (figure), n %= (figure)); \
- DIGITS_6 ((figure) / 10)
-#define DIGITS_8(figure) \
- (ONE_DIGIT (figure), n %= (figure)); \
- DIGITS_7 ((figure) / 10)
-#define DIGITS_9(figure) \
- (ONE_DIGIT (figure), n %= (figure)); \
- DIGITS_8 ((figure) / 10)
-#define DIGITS_10(figure) \
- (ONE_DIGIT (figure), n %= (figure)); \
- DIGITS_9 ((figure) / 10)
-
-/* DIGITS_<11-20> are only used on 64-bit machines. */
-
-#define DIGITS_11(figure) \
- (ONE_DIGIT (figure), n %= (figure)); \
- DIGITS_10 ((figure) / 10)
-#define DIGITS_12(figure) \
- (ONE_DIGIT (figure), n %= (figure)); \
- DIGITS_11 ((figure) / 10)
-#define DIGITS_13(figure) \
- (ONE_DIGIT (figure), n %= (figure)); \
- DIGITS_12 ((figure) / 10)
-#define DIGITS_14(figure) \
- (ONE_DIGIT (figure), n %= (figure)); \
- DIGITS_13 ((figure) / 10)
-#define DIGITS_15(figure) \
- (ONE_DIGIT (figure), n %= (figure)); \
- DIGITS_14 ((figure) / 10)
-#define DIGITS_16(figure) \
- (ONE_DIGIT (figure), n %= (figure)); \
- DIGITS_15 ((figure) / 10)
-#define DIGITS_17(figure) \
- (ONE_DIGIT (figure), n %= (figure)); \
- DIGITS_16 ((figure) / 10)
-#define DIGITS_18(figure) \
- (ONE_DIGIT (figure), n %= (figure)); \
- DIGITS_17 ((figure) / 10)
-#define DIGITS_19(figure) \
- (ONE_DIGIT (figure), n %= (figure)); \
- DIGITS_18 ((figure) / 10)
+#define ONE_DIGIT_ADVANCE(figure) (ONE_DIGIT (figure), n %= (figure))
+
+#define DIGITS_1(figure) ONE_DIGIT (figure)
+#define DIGITS_2(figure) ONE_DIGIT_ADVANCE (figure); DIGITS_1 ((figure) / 10)
+#define DIGITS_3(figure) ONE_DIGIT_ADVANCE (figure); DIGITS_2 ((figure) / 10)
+#define DIGITS_4(figure) ONE_DIGIT_ADVANCE (figure); DIGITS_3 ((figure) / 10)
+#define DIGITS_5(figure) ONE_DIGIT_ADVANCE (figure); DIGITS_4 ((figure) / 10)
+#define DIGITS_6(figure) ONE_DIGIT_ADVANCE (figure); DIGITS_5 ((figure) / 10)
+#define DIGITS_7(figure) ONE_DIGIT_ADVANCE (figure); DIGITS_6 ((figure) / 10)
+#define DIGITS_8(figure) ONE_DIGIT_ADVANCE (figure); DIGITS_7 ((figure) / 10)
+#define DIGITS_9(figure) ONE_DIGIT_ADVANCE (figure); DIGITS_8 ((figure) / 10)
+#define DIGITS_10(figure) ONE_DIGIT_ADVANCE (figure); DIGITS_9 ((figure) / 10)
+
+/* DIGITS_<11-20> are only used on machines with 64-bit longs. */
+
+#define DIGITS_11(figure) ONE_DIGIT_ADVANCE (figure); DIGITS_10 ((figure) / 10)
+#define DIGITS_12(figure) ONE_DIGIT_ADVANCE (figure); DIGITS_11 ((figure) / 10)
+#define DIGITS_13(figure) ONE_DIGIT_ADVANCE (figure); DIGITS_12 ((figure) / 10)
+#define DIGITS_14(figure) ONE_DIGIT_ADVANCE (figure); DIGITS_13 ((figure) / 10)
+#define DIGITS_15(figure) ONE_DIGIT_ADVANCE (figure); DIGITS_14 ((figure) / 10)
+#define DIGITS_16(figure) ONE_DIGIT_ADVANCE (figure); DIGITS_15 ((figure) / 10)
+#define DIGITS_17(figure) ONE_DIGIT_ADVANCE (figure); DIGITS_16 ((figure) / 10)
+#define DIGITS_18(figure) ONE_DIGIT_ADVANCE (figure); DIGITS_17 ((figure) / 10)
+#define DIGITS_19(figure) ONE_DIGIT_ADVANCE (figure); DIGITS_18 ((figure) / 10)
/* Print NUMBER to BUFFER in base 10. This is completely equivalent
to `sprintf(buffer, "%ld", number)', only much faster.
slow compared to this function.
BUFFER should accept as many bytes as you expect the number to take
- up. On 64-bit machines, the maximum needed size is 24 bytes. That
- includes all the digits, as well as the `-' sign for negative
- numbers and the trailing \0. */
+ up. On machines with 64-bit longs the maximum needed size is 24
+ bytes. That includes the worst-case digits, the optional `-' sign,
+ and the trailing \0. */
void
long_to_string (char *buffer, long number)
}
#undef ONE_DIGIT
+#undef ONE_DIGIT_ADVANCE
+
#undef DIGITS_1
#undef DIGITS_2
#undef DIGITS_3
#undef DIGITS_18
#undef DIGITS_19
\f
+/* Support for timers. */
+
+#undef TIMER_WINDOWS
+#undef TIMER_GETTIMEOFDAY
+#undef TIMER_TIME
+
+/* Depending on the OS and availability of gettimeofday(), one and
+ only one of the above constants will be defined. Virtually all
+ modern Unix systems will define TIMER_GETTIMEOFDAY; Windows will
+ use TIMER_WINDOWS. TIMER_TIME is a catch-all method for
+ non-Windows systems without gettimeofday.
+
+ #### Perhaps we should also support ftime(), which exists on old
+ BSD 4.2-influenced systems? (It also existed under MS DOS Borland
+ C, if memory serves me.) */
+
+#ifdef WINDOWS
+# define TIMER_WINDOWS
+#else /* not WINDOWS */
+# ifdef HAVE_GETTIMEOFDAY
+# define TIMER_GETTIMEOFDAY
+# else
+# define TIMER_TIME
+# endif
+#endif /* not WINDOWS */
+
+struct wget_timer {
+#ifdef TIMER_GETTIMEOFDAY
+ long secs;
+ long usecs;
+#endif
+
+#ifdef TIMER_TIME
+ time_t secs;
+#endif
+
+#ifdef TIMER_WINDOWS
+ ULARGE_INTEGER wintime;
+#endif
+};
+
+/* Allocate a timer. It is not legal to do anything with a freshly
+ allocated timer, except call wtimer_reset() or wtimer_delete(). */
+
+struct wget_timer *
+wtimer_allocate (void)
+{
+ struct wget_timer *wt =
+ (struct wget_timer *)xmalloc (sizeof (struct wget_timer));
+ return wt;
+}
+
+/* Allocate a new timer and reset it. Return the new timer. */
+
+struct wget_timer *
+wtimer_new (void)
+{
+ struct wget_timer *wt = wtimer_allocate ();
+ wtimer_reset (wt);
+ return wt;
+}
+
+/* Free the resources associated with the timer. Its further use is
+ prohibited. */
+
+void
+wtimer_delete (struct wget_timer *wt)
+{
+ xfree (wt);
+}
+
+/* Reset timer WT. This establishes the starting point from which
+ wtimer_elapsed() will return the number of elapsed
+ milliseconds. It is allowed to reset a previously used timer. */
+
+void
+wtimer_reset (struct wget_timer *wt)
+{
+#ifdef TIMER_GETTIMEOFDAY
+ struct timeval t;
+ gettimeofday (&t, NULL);
+ wt->secs = t.tv_sec;
+ wt->usecs = t.tv_usec;
+#endif
+
+#ifdef TIMER_TIME
+ wt->secs = time (NULL);
+#endif
+
+#ifdef TIMER_WINDOWS
+ FILETIME ft;
+ SYSTEMTIME st;
+ GetSystemTime (&st);
+ SystemTimeToFileTime (&st, &ft);
+ wt->wintime.HighPart = ft.dwHighDateTime;
+ wt->wintime.LowPart = ft.dwLowDateTime;
+#endif
+}
+
+/* Return the number of milliseconds elapsed since the timer was last
+ reset. It is allowed to call this function more than once to get
+ increasingly higher elapsed values. */
+
+long
+wtimer_elapsed (struct wget_timer *wt)
+{
+#ifdef TIMER_GETTIMEOFDAY
+ struct timeval t;
+ gettimeofday (&t, NULL);
+ return (t.tv_sec - wt->secs) * 1000 + (t.tv_usec - wt->usecs) / 1000;
+#endif
+
+#ifdef TIMER_TIME
+ time_t now = time (NULL);
+ return 1000 * (now - wt->secs);
+#endif
+
+#ifdef WINDOWS
+ FILETIME ft;
+ SYSTEMTIME st;
+ ULARGE_INTEGER uli;
+ GetSystemTime (&st);
+ SystemTimeToFileTime (&st, &ft);
+ uli.HighPart = ft.dwHighDateTime;
+ uli.LowPart = ft.dwLowDateTime;
+ return (long)((uli.QuadPart - wt->wintime.QuadPart) / 10000);
+#endif
+}
+
+/* Return the assessed granularity of the timer implementation. This
+ is important for certain code that tries to deal with "zero" time
+ intervals. */
+
+long
+wtimer_granularity (void)
+{
+#ifdef TIMER_GETTIMEOFDAY
+ /* Granularity of gettimeofday is hugely architecture-dependent.
+ However, it appears that on modern machines it is better than
+ 1ms. */
+ return 1;
+#endif
+
+#ifdef TIMER_TIME
+ /* This is clear. */
+ return 1000;
+#endif
+
+#ifdef TIMER_WINDOWS
+ /* ? */
+ return 1;
+#endif
+}
+\f
/* This should probably be at a better place, but it doesn't really
fit into html-parse.c. */