Peter Eisentraut wrote: > Magnus Hagander wrote: >> How do I make this work with the autoconf magic? I see there is an >> AC_CHECK_FNMATCH and AC_REPLACE_FNMATCH and so, but I have a feeling I >> need to do something different since it's libpq? > > AC_*_FNMATCH will figure out whether you need fnmatch(), so something > involving those is necessary. > > For libpq, check libpq's Makefile for, say, snprintf, to get an idea > about the "something different". > > Altogether, this might not be a trivial case.
Hmm. If I did it the right way, it actually didn't seem too hard once I found a good example. Attached - does that seem reasonable? (will add msvc code as well) //Magnus
*** a/configure --- b/configure *************** *** 16930,16936 **** LIBS=`echo "$LIBS" | sed -e 's/-ledit//g' -e 's/-lreadline//g'` ! for ac_func in crypt getopt getrusage inet_aton random rint srandom strdup strerror strlcat strlcpy strtol strtoul unsetenv do as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` { echo "$as_me:$LINENO: checking for $ac_func" >&5 --- 16930,16937 ---- ! ! for ac_func in crypt fnmatch getopt getrusage inet_aton random rint srandom strdup strerror strlcat strlcpy strtol strtoul unsetenv do as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` { echo "$as_me:$LINENO: checking for $ac_func" >&5 *** a/configure.in --- b/configure.in *************** *** 1235,1241 **** fi pgac_save_LIBS="$LIBS" LIBS=`echo "$LIBS" | sed -e 's/-ledit//g' -e 's/-lreadline//g'` ! AC_REPLACE_FUNCS([crypt getopt getrusage inet_aton random rint srandom strdup strerror strlcat strlcpy strtol strtoul unsetenv]) LIBS="$pgac_save_LIBS" --- 1235,1241 ---- pgac_save_LIBS="$LIBS" LIBS=`echo "$LIBS" | sed -e 's/-ledit//g' -e 's/-lreadline//g'` ! AC_REPLACE_FUNCS([crypt fnmatch getopt getrusage inet_aton random rint srandom strdup strerror strlcat strlcpy strtol strtoul unsetenv]) LIBS="$pgac_save_LIBS" *** a/src/include/pg_config.h.in --- b/src/include/pg_config.h.in *************** *** 143,148 **** --- 143,151 ---- /* Define to 1 if you have the `fdatasync' function. */ #undef HAVE_FDATASYNC + /* Define to 1 if you have the `fnmatch' function. */ + #undef HAVE_FNMATCH + /* Define to 1 if you have the `fpclass' function. */ #undef HAVE_FPCLASS *** a/src/include/port.h --- b/src/include/port.h *************** *** 393,398 **** extern void unsetenv(const char *name); --- 393,409 ---- extern void srandom(unsigned int seed); #endif + #ifdef HAVE_FNMATCH + extern int fnmatch(const char *, const char *, int); + #define FNM_NOMATCH 1 /* Match failed. */ + #define FNM_NOSYS 2 /* Function not implemented. */ + #define FNM_NOESCAPE 0x01 /* Disable backslash escaping. */ + #define FNM_PATHNAME 0x02 /* Slash must be matched by slash. */ + #define FNM_PERIOD 0x04 /* Period must be matched by period. */ + #define FNM_CASEFOLD 0x08 /* Pattern is matched case-insensitive */ + #define FNM_LEADING_DIR 0x10 /* Ignore /<tail> after Imatch. */ + #endif + /* thread.h */ extern char *pqStrerror(int errnum, char *strerrbuf, size_t buflen); *** a/src/interfaces/libpq/Makefile --- b/src/interfaces/libpq/Makefile *************** *** 34,40 **** OBJS= fe-auth.o fe-connect.o fe-exec.o fe-misc.o fe-print.o fe-lobj.o \ fe-protocol2.o fe-protocol3.o pqexpbuffer.o pqsignal.o fe-secure.o \ libpq-events.o \ md5.o ip.o wchar.o encnames.o noblock.o pgstrcasecmp.o thread.o \ ! $(filter crypt.o getaddrinfo.o inet_aton.o open.o snprintf.o strerror.o strlcpy.o win32error.o, $(LIBOBJS)) ifeq ($(PORTNAME), cygwin) override shlib = cyg$(NAME)$(DLSUFFIX) --- 34,40 ---- fe-protocol2.o fe-protocol3.o pqexpbuffer.o pqsignal.o fe-secure.o \ libpq-events.o \ md5.o ip.o wchar.o encnames.o noblock.o pgstrcasecmp.o thread.o \ ! $(filter crypt.o fnmatch.o getaddrinfo.o inet_aton.o open.o snprintf.o strerror.o strlcpy.o win32error.o, $(LIBOBJS)) ifeq ($(PORTNAME), cygwin) override shlib = cyg$(NAME)$(DLSUFFIX) *************** *** 80,86 **** backend_src = $(top_srcdir)/src/backend # For port modules, this only happens if configure decides the module # is needed (see filter hack in OBJS, above). ! crypt.c getaddrinfo.c inet_aton.c noblock.c open.c pgstrcasecmp.c snprintf.c strerror.c strlcpy.c thread.c win32error.c pgsleep.c: % : $(top_srcdir)/src/port/% rm -f $@ && $(LN_S) $< . md5.c ip.c: % : $(backend_src)/libpq/% --- 80,86 ---- # For port modules, this only happens if configure decides the module # is needed (see filter hack in OBJS, above). ! crypt.c fnmatch.c getaddrinfo.c inet_aton.c noblock.c open.c pgstrcasecmp.c snprintf.c strerror.c strlcpy.c thread.c win32error.c pgsleep.c: % : $(top_srcdir)/src/port/% rm -f $@ && $(LN_S) $< . md5.c ip.c: % : $(backend_src)/libpq/% *************** *** 123,129 **** uninstall: uninstall-lib rm -f '$(DESTDIR)$(datadir)/pg_service.conf.sample' clean distclean: clean-lib ! rm -f $(OBJS) pg_config_paths.h crypt.c getaddrinfo.c inet_aton.c noblock.c open.c pgstrcasecmp.c snprintf.c strerror.c strlcpy.c thread.c md5.c ip.c encnames.c wchar.c win32error.c pgsleep.c pthread.h libpq.rc # Might be left over from a Win32 client-only build rm -f pg_config_paths.h --- 123,129 ---- rm -f '$(DESTDIR)$(datadir)/pg_service.conf.sample' clean distclean: clean-lib ! rm -f $(OBJS) pg_config_paths.h crypt.c fnmatch.c getaddrinfo.c inet_aton.c noblock.c open.c pgstrcasecmp.c snprintf.c strerror.c strlcpy.c thread.c md5.c ip.c encnames.c wchar.c win32error.c pgsleep.c pthread.h libpq.rc # Might be left over from a Win32 client-only build rm -f pg_config_paths.h *** a/src/interfaces/libpq/fe-secure.c --- b/src/interfaces/libpq/fe-secure.c *************** *** 63,68 **** --- 63,73 ---- #if (SSLEAY_VERSION_NUMBER >= 0x00907000L) && !defined(OPENSSL_NO_ENGINE) #include <openssl/engine.h> #endif + + /* fnmatch() needed for client certificate mapping */ + #ifdef HAVE_FNMATCH + #include <fnmatch.h> + #endif #endif /* USE_SSL */ *************** *** 461,477 **** verify_peer_name_matches_certificate(PGconn *conn) * Connect by hostname. * * XXX: Should support alternate names here - * XXX: Should support wildcard certificates here */ ! if (pg_strcasecmp(conn->peer_cn, conn->pghost) != 0) { printfPQExpBuffer(&conn->errorMessage, libpq_gettext("server common name '%s' does not match hostname '%s'"), conn->peer_cn, conn->pghost); return false; } - else - return true; } } --- 466,485 ---- * Connect by hostname. * * XXX: Should support alternate names here */ ! if (pg_strcasecmp(conn->peer_cn, conn->pghost) == 0) ! /* Exact name match */ ! return true; ! else if (fnmatch(conn->peer_cn, conn->pghost, FNM_NOESCAPE | FNM_CASEFOLD) == 0) ! /* Matched wildcard certificate */ ! return true; ! else { printfPQExpBuffer(&conn->errorMessage, libpq_gettext("server common name '%s' does not match hostname '%s'"), conn->peer_cn, conn->pghost); return false; } } } *** /dev/null --- b/src/port/fnmatch.c *************** *** 0 **** --- 1,197 ---- + /*------------------------------------------------------------------------- + * + * fnmatch.c + * fnmatch() - wildcard matching function + * + * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group + * + * + * IDENTIFICATION + * $PostgreSQL$ + * + * This file was taken from NetBSD and is used on platforms that don't + * provide fnmatch(). The NetBSD copyright terms follow. + *------------------------------------------------------------------------- + */ + + /* $NetBSD: fnmatch.c,v 1.21 2005/12/24 21:11:16 perry Exp $ */ + + /* + * Copyright (c) 1989, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Guido van Rossum. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + /* + * Function fnmatch() as specified in POSIX 1003.2-1992, section B.6. + * Compares a filename or pathname to a pattern. + */ + + #include "c.h" + + #define EOS '\0' + + static const char *rangematch (const char *, int, int); + + static inline int + foldcase(int ch, int flags) + { + + if ((flags & FNM_CASEFOLD) != 0 && isupper(ch)) + return (tolower(ch)); + return (ch); + } + + #define FOLDCASE(ch, flags) foldcase((unsigned char)(ch), (flags)) + + int + fnmatch(pattern, string, flags) + const char *pattern, *string; + int flags; + { + const char *stringstart; + char c, test; + + for (stringstart = string;;) + switch (c = FOLDCASE(*pattern++, flags)) { + case EOS: + if ((flags & FNM_LEADING_DIR) && *string == '/') + return (0); + return (*string == EOS ? 0 : FNM_NOMATCH); + case '?': + if (*string == EOS) + return (FNM_NOMATCH); + if (*string == '/' && (flags & FNM_PATHNAME)) + return (FNM_NOMATCH); + if (*string == '.' && (flags & FNM_PERIOD) && + (string == stringstart || + ((flags & FNM_PATHNAME) && *(string - 1) == '/'))) + return (FNM_NOMATCH); + ++string; + break; + case '*': + c = FOLDCASE(*pattern, flags); + /* Collapse multiple stars. */ + while (c == '*') + c = FOLDCASE(*++pattern, flags); + + if (*string == '.' && (flags & FNM_PERIOD) && + (string == stringstart || + ((flags & FNM_PATHNAME) && *(string - 1) == '/'))) + return (FNM_NOMATCH); + + /* Optimize for pattern with * at end or before /. */ + if (c == EOS) { + if (flags & FNM_PATHNAME) + return ((flags & FNM_LEADING_DIR) || + strchr(string, '/') == NULL ? + 0 : FNM_NOMATCH); + else + return (0); + } else if (c == '/' && flags & FNM_PATHNAME) { + if ((string = strchr(string, '/')) == NULL) + return (FNM_NOMATCH); + break; + } + + /* General case, use recursion. */ + while ((test = FOLDCASE(*string, flags)) != EOS) { + if (!fnmatch(pattern, string, + flags & ~FNM_PERIOD)) + return (0); + if (test == '/' && flags & FNM_PATHNAME) + break; + ++string; + } + return (FNM_NOMATCH); + case '[': + if (*string == EOS) + return (FNM_NOMATCH); + if (*string == '/' && flags & FNM_PATHNAME) + return (FNM_NOMATCH); + if ((pattern = + rangematch(pattern, FOLDCASE(*string, flags), + flags)) == NULL) + return (FNM_NOMATCH); + ++string; + break; + case '\\': + if (!(flags & FNM_NOESCAPE)) { + if ((c = FOLDCASE(*pattern++, flags)) == EOS) { + c = '\\'; + --pattern; + } + } + /* FALLTHROUGH */ + default: + if (c != FOLDCASE(*string++, flags)) + return (FNM_NOMATCH); + break; + } + /* NOTREACHED */ + } + + static const char * + rangematch(pattern, test, flags) + const char *pattern; + int test, flags; + { + int negate, ok; + char c, c2; + + /* + * A bracket expression starting with an unquoted circumflex + * character produces unspecified results (IEEE 1003.2-1992, + * 3.13.2). This implementation treats it like '!', for + * consistency with the regular expression syntax. + * J.T. Conklin ([EMAIL PROTECTED]) + */ + if ((negate = (*pattern == '!' || *pattern == '^')) != 0) + ++pattern; + + for (ok = 0; (c = FOLDCASE(*pattern++, flags)) != ']';) { + if (c == '\\' && !(flags & FNM_NOESCAPE)) + c = FOLDCASE(*pattern++, flags); + if (c == EOS) + return (NULL); + if (*pattern == '-' + && (c2 = FOLDCASE(*(pattern+1), flags)) != EOS && + c2 != ']') { + pattern += 2; + if (c2 == '\\' && !(flags & FNM_NOESCAPE)) + c2 = FOLDCASE(*pattern++, flags); + if (c2 == EOS) + return (NULL); + if (c <= test && test <= c2) + ok = 1; + } else if (c == test) + ok = 1; + } + return (ok == negate ? NULL : pattern); + }
-- Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-hackers