/* Replacements for routines missing on some systems.
- Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc.
+ Copyright (C) 1995-2005 Free Software Foundation, Inc.
This file is part of GNU Wget.
#include <stdio.h>
#include <stdlib.h>
-#ifdef HAVE_STRING_H
-# include <string.h>
-#else
-# include <strings.h>
-#endif /* HAVE_STRING_H */
+#include <string.h>
-#include <sys/types.h>
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
-#include <limits.h>
-#include "wget.h"
+#include <errno.h>
-#ifndef HAVE_STRERROR
-/* A strerror() clone, for systems that don't have it. */
-char *
-strerror (int err)
-{
- /* This loses on a system without `sys_errlist'. */
- extern char *sys_errlist[];
- return sys_errlist[err];
-}
-#endif /* not HAVE_STRERROR */
+#include "wget.h"
/* Some systems don't have some str* functions in libc. Here we
define them. The same goes for strptime. */
}
#endif /* not HAVE_STRNCASECMP */
-#ifndef HAVE_STRSTR
-/* From GNU libc 2.0.6. */
-/* Return the first ocurrence of NEEDLE in HAYSTACK. */
-/*
- * My personal strstr() implementation that beats most other algorithms.
- * Until someone tells me otherwise, I assume that this is the
- * fastest implementation of strstr() in C.
- * I deliberately chose not to comment it. You should have at least
- * as much fun trying to understand it, as I had to write it :-).
- *
- * Stephen R. van den Berg, berg@pool.informatik.rwth-aachen.de */
-typedef unsigned chartype;
-
-char *
-strstr (phaystack, pneedle)
- const char *phaystack;
- const char *pneedle;
-{
- register const unsigned char *haystack, *needle;
- register chartype b, c;
-
- haystack = (const unsigned char *) phaystack;
- needle = (const unsigned char *) pneedle;
-
- b = *needle;
- if (b != '\0')
- {
- haystack--; /* possible ANSI violation */
- do
- {
- c = *++haystack;
- if (c == '\0')
- goto ret0;
- }
- while (c != b);
-
- c = *++needle;
- if (c == '\0')
- goto foundneedle;
- ++needle;
- goto jin;
-
- for (;;)
- {
- register chartype a;
- register const unsigned char *rhaystack, *rneedle;
-
- do
- {
- a = *++haystack;
- if (a == '\0')
- goto ret0;
- if (a == b)
- break;
- a = *++haystack;
- if (a == '\0')
- goto ret0;
-shloop: }
- while (a != b);
-
-jin: a = *++haystack;
- if (a == '\0')
- goto ret0;
-
- if (a != c)
- goto shloop;
-
- rhaystack = haystack-- + 1;
- rneedle = needle;
- a = *rneedle;
-
- if (*rhaystack == a)
- do
- {
- if (a == '\0')
- goto foundneedle;
- ++rhaystack;
- a = *++needle;
- if (*rhaystack != a)
- break;
- if (a == '\0')
- goto foundneedle;
- ++rhaystack;
- a = *++needle;
- }
- while (*rhaystack == a);
-
- needle = rneedle; /* took the register-poor approach */
-
- if (a == '\0')
- break;
- }
- }
-foundneedle:
- return (char*) haystack;
-ret0:
- return 0;
-}
-#endif /* not HAVE_STRSTR */
-
#ifndef HAVE_STRPBRK
/* Find the first ocurrence in S of any character in ACCEPT. */
char *
#endif
#ifndef __P
-# define __P(args) PARAMS (args)
+# define __P(args) args
#endif /* Not __P. */
#ifndef CHAR_BIT
this is enough information for determining the date. */
#ifndef __P
-# define __P(args) PARAMS (args)
+# define __P(args) args
#endif /* not __P */
#if ! HAVE_LOCALTIME_R && ! defined localtime_r
struct tm *tm;
enum locale_status *decided;
{
+#ifdef _NL_CURRENT
const char *rp_backup;
+#endif
int cnt;
size_t val;
int have_I, is_pm;
start_over:
#endif
+#ifdef _NL_CURRENT
/* Make back up of current processing pointer. */
rp_backup = rp;
+#endif
switch (*fmt++)
{
};
#endif
-#ifndef HAVE_USLEEP
-#ifndef WINDOWS
+/* fnmatch is defined by POSIX, but we include an implementation for
+ the sake of systems that don't have it. Some systems do have
+ fnmatch, but Apache installs its own fnmatch.h (incompatible with
+ the system one) in a system include directory, effectively
+ rendering fnmatch unusable.
+
+ Additionally according to anecdotal evidence and conventional
+ wisdom I lack courage to challenge, many implementations of fnmatch
+ are notoriously buggy and unreliable. So we use our version by
+ default, except when compiling under systems where fnmatch is known
+ to work (currently on GNU libc-based systems and Solaris.) */
+
+#ifndef SYSTEM_FNMATCH
-/* A simple usleep implementation based on select(). For Unix and
- Unix-like systems. */
+#define __FNM_FLAGS (FNM_PATHNAME | FNM_NOESCAPE | FNM_PERIOD)
+
+/* Match STRING against the filename pattern PATTERN, returning zero
+ if it matches, FNM_NOMATCH if not. This implementation comes from
+ an earlier version of GNU Bash. (It doesn't make sense to update
+ it with a newer version because those versions add a lot of
+ features Wget doesn't use or care about.) */
int
-usleep (unsigned long usec)
+fnmatch (const char *pattern, const char *string, int flags)
{
- struct timeval tm;
- tm.tv_sec = 0;
- tm.tv_usec = usec;
- select (0, NULL, NULL, NULL, &tm);
- return 0;
-}
+ register const char *p = pattern, *n = string;
+ register char c;
+
+ if ((flags & ~__FNM_FLAGS) != 0)
+ {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ while ((c = *p++) != '\0')
+ {
+ switch (c)
+ {
+ case '?':
+ if (*n == '\0')
+ return (FNM_NOMATCH);
+ else if ((flags & FNM_PATHNAME) && *n == '/')
+ return (FNM_NOMATCH);
+ else if ((flags & FNM_PERIOD) && *n == '.' &&
+ (n == string || ((flags & FNM_PATHNAME) && n[-1] == '/')))
+ return (FNM_NOMATCH);
+ break;
-#endif /* not WINDOWS */
-#endif /* not HAVE_USLEEP */
+ case '\\':
+ if (!(flags & FNM_NOESCAPE))
+ c = *p++;
+ if (*n != c)
+ return (FNM_NOMATCH);
+ break;
+ case '*':
+ if ((flags & FNM_PERIOD) && *n == '.' &&
+ (n == string || ((flags & FNM_PATHNAME) && n[-1] == '/')))
+ return (FNM_NOMATCH);
-/* Currently unused in Wget. Uncomment if we start using memmove
- again. */
-#if 0
+ for (c = *p++; c == '?' || c == '*'; c = *p++, ++n)
+ if (((flags & FNM_PATHNAME) && *n == '/') ||
+ (c == '?' && *n == '\0'))
+ return (FNM_NOMATCH);
-#ifndef HAVE_MEMMOVE
-void *
-memmove (char *dest, const char *source, unsigned length)
-{
- char *d0 = dest;
- if (source < dest)
- /* Moving from low mem to hi mem; start at end. */
- for (source += length, dest += length; length; --length)
- *--dest = *--source;
- else if (source != dest)
- {
- /* Moving from hi mem to low mem; start at beginning. */
- for (; length; --length)
- *dest++ = *source++;
+ if (c == '\0')
+ return (0);
+
+ {
+ char c1 = (!(flags & FNM_NOESCAPE) && c == '\\') ? *p : c;
+ for (--p; *n != '\0'; ++n)
+ if ((c == '[' || *n == c1) &&
+ fnmatch (p, n, flags & ~FNM_PERIOD) == 0)
+ return (0);
+ return (FNM_NOMATCH);
+ }
+
+ case '[':
+ {
+ /* Nonzero if the sense of the character class is
+ inverted. */
+ register int not;
+
+ if (*n == '\0')
+ return (FNM_NOMATCH);
+
+ if ((flags & FNM_PERIOD) && *n == '.' &&
+ (n == string || ((flags & FNM_PATHNAME) && n[-1] == '/')))
+ return (FNM_NOMATCH);
+
+ /* Make sure there is a closing `]'. If there isn't,
+ the `[' is just a character to be matched. */
+ {
+ register const char *np;
+
+ for (np = p; np && *np && *np != ']'; np++);
+
+ if (np && !*np)
+ {
+ if (*n != '[')
+ return (FNM_NOMATCH);
+ goto next_char;
+ }
+ }
+
+ not = (*p == '!' || *p == '^');
+ if (not)
+ ++p;
+
+ c = *p++;
+ while (1)
+ {
+ register char cstart = c, cend = c;
+
+ if (!(flags & FNM_NOESCAPE) && c == '\\')
+ cstart = cend = *p++;
+
+ if (c == '\0')
+ /* [ (unterminated) loses. */
+ return (FNM_NOMATCH);
+
+ c = *p++;
+
+ if ((flags & FNM_PATHNAME) && c == '/')
+ /* [/] can never match. */
+ return (FNM_NOMATCH);
+
+ if (c == '-' && *p != ']')
+ {
+ cend = *p++;
+ if (!(flags & FNM_NOESCAPE) && cend == '\\')
+ cend = *p++;
+ if (cend == '\0')
+ return (FNM_NOMATCH);
+ c = *p++;
+ }
+
+ if (*n >= cstart && *n <= cend)
+ goto matched;
+
+ if (c == ']')
+ break;
+ }
+ if (!not)
+ return (FNM_NOMATCH);
+
+ next_char:
+ break;
+
+ matched:
+ /* Skip the rest of the [...] that already matched. */
+ while (c != ']')
+ {
+ if (c == '\0')
+ /* [... (unterminated) loses. */
+ return (FNM_NOMATCH);
+
+ c = *p++;
+ if (!(flags & FNM_NOESCAPE) && c == '\\')
+ /* 1003.2d11 is unclear if this is right. %%% */
+ ++p;
+ }
+ if (not)
+ return (FNM_NOMATCH);
+ }
+ break;
+
+ default:
+ if (c != *n)
+ return (FNM_NOMATCH);
+ }
+
+ ++n;
}
- return (void *) d0;
+
+ if (*n == '\0')
+ return (0);
+
+ return (FNM_NOMATCH);
}
-#endif /* not HAVE_MEMMOVE */
-#endif /* 0 */
+#endif /* not SYSTEM_FNMATCH */