change default sudoers to allow group changes
[debian/sudo] / fnmatch.c
index 4a9c4d3f9f91747cc698e5fc51a5eefed4720cfb..2255e521444a4bddb561bd3e162133296cae5ac0 100644 (file)
--- a/fnmatch.c
+++ b/fnmatch.c
@@ -1,4 +1,5 @@
 /*
+ * Copyright (c) 2008, 2010 Todd C. Miller <Todd.Miller@courtesan.com>
  * Copyright (c) 1989, 1993, 1994
  *     The Regents of the University of California.  All rights reserved.
  *
  * SUCH DAMAGE.
  */
 
-#if defined(LIBC_SCCS) && !defined(lint)
-static char rcsid[] = "$OpenBSD: fnmatch.c,v 1.6 1998/03/19 00:29:59 millert Exp $";
-#endif /* LIBC_SCCS and not lint */
-
 /*
  * Function fnmatch() as specified in POSIX 1003.2-1992, section B.6.
  * Compares a filename or pathname to a pattern.
  */
 
-#include "config.h"
+#include <config.h>
 
 #include <stdio.h>
 #include <ctype.h>
 #ifdef HAVE_STRING_H
 # include <string.h>
-#else
-# ifdef HAVE_STRINGS_H
-#  include <strings.h>
-# endif
 #endif /* HAVE_STRING_H */
+#ifdef HAVE_STRINGS_H
+# include <strings.h>
+#endif /* HAVE_STRINGS_H */
 
-#include "compat.h"
+#include <compat.h>
 #include "emul/fnmatch.h"
+#include "emul/charclass.h"
 
 #undef EOS
 #define        EOS     '\0'
@@ -61,7 +58,12 @@ static char rcsid[] = "$OpenBSD: fnmatch.c,v 1.6 1998/03/19 00:29:59 millert Exp
 #define        RANGE_NOMATCH   0
 #define        RANGE_ERROR     (-1)
 
-static int rangematch __P((const char *, char, int, char **));
+#if defined(LIBC_SCCS) && !defined(lint)
+__unused static const char rcsid[] = "$OpenBSD: fnmatch.c,v 1.6 1998/03/19 00:29:59 millert Exp $";
+#endif /* LIBC_SCCS and not lint */
+
+static int rangematch __P((const char *, int, int, char **));
+static int classmatch __P((const char *, int, int, const char **));
 
 int
 fnmatch(pattern, string, flags)
@@ -167,16 +169,16 @@ fnmatch(pattern, string, flags)
 
 static int
 #ifdef __STDC__
-rangematch(const char *pattern, char test, int flags, char **newp)
+rangematch(const char *pattern, int test, int flags, char **newp)
 #else
 rangematch(pattern, test, flags, newp)
        const char *pattern;
-       char test;
+       int test;
        int flags;
        char **newp;
 #endif
 {
-       int negate, ok;
+       int negate, ok, rv;
        char c, c2;
 
        /*
@@ -190,7 +192,7 @@ rangematch(pattern, test, flags, newp)
                ++pattern;
 
        if (ISSET(flags, FNM_CASEFOLD))
-               test = tolower((unsigned char)test);
+               test = tolower(test);
 
        /*
         * A right bracket shall lose its special meaning and represent
@@ -200,6 +202,17 @@ rangematch(pattern, test, flags, newp)
        ok = 0;
        c = *pattern++;
        do {
+               if (c == '[' && *pattern == ':') {
+                       do {
+                               rv = classmatch(pattern + 1, test,
+                                   (flags & FNM_CASEFOLD), &pattern);
+                               if (rv == RANGE_MATCH)
+                                       ok = 1;
+                               c = *pattern++;
+                       } while (rv != RANGE_ERROR && c == '[' && *pattern == ':');
+                       if (c == ']')
+                       break;
+               }
                if (c == '\\' && !ISSET(flags, FNM_NOESCAPE))
                        c = *pattern++;
                if (c == EOS)
@@ -226,3 +239,43 @@ rangematch(pattern, test, flags, newp)
        *newp = (char *)pattern;
        return (ok == negate ? RANGE_NOMATCH : RANGE_MATCH);
 }
+
+static int
+#ifdef __STDC__
+classmatch(const char *pattern, int test, int foldcase, const char **ep)
+#else
+classmatch(pattern, test, foldcase, ep)
+       const char *pattern;
+       int test;
+       int foldcase;
+       const char **ep;
+#endif
+{
+       struct cclass *cc;
+       const char *colon;
+       size_t len;
+       int rval = RANGE_NOMATCH;
+
+       if ((colon = strchr(pattern, ':')) == NULL || colon[1] != ']') {
+               *ep = pattern - 2;
+               return(RANGE_ERROR);
+       }
+       *ep = colon + 2;
+       len = (size_t)(colon - pattern);
+
+       if (foldcase && strncmp(pattern, "upper:]", 7) == 0)
+               pattern = "lower:]";
+       for (cc = cclasses; cc->name != NULL; cc++) {
+               if (!strncmp(pattern, cc->name, len) && cc->name[len] == '\0') {
+                       if (cc->isctype(test))
+                               rval = RANGE_MATCH;
+                       break;
+               }
+       }
+       if (cc->name == NULL) {
+               /* invalid character class, return EOS */
+               *ep = colon + strlen(colon);
+               rval = RANGE_ERROR;
+       }
+       return(rval);
+}