139734Sbostic /* 2*61111Sbostic * Copyright (c) 1989, 1993 3*61111Sbostic * The Regents of the University of California. All rights reserved. 439734Sbostic * 539734Sbostic * This code is derived from software contributed to Berkeley by 639734Sbostic * Guido van Rossum. 739734Sbostic * 842624Sbostic * %sccs.include.redist.c% 939734Sbostic */ 1039734Sbostic 1139734Sbostic #if defined(LIBC_SCCS) && !defined(lint) 12*61111Sbostic static char sccsid[] = "@(#)fnmatch.c 8.1 (Berkeley) 06/04/93"; 1339734Sbostic #endif /* LIBC_SCCS and not lint */ 1439734Sbostic 1539734Sbostic /* 1654535Sbostic * Function fnmatch() as proposed in POSIX 1003.2 B.6 (D11.2). 1739734Sbostic * Compares a filename or pathname to a pattern. 1839734Sbostic */ 1939734Sbostic 2054534Sbostic #include <fnmatch.h> 2139734Sbostic #include <string.h> 2239734Sbostic 2339734Sbostic #define EOS '\0' 2439734Sbostic 2554535Sbostic static const char *rangematch __P((const char *, int)); 2643528Sbostic 2739734Sbostic fnmatch(pattern, string, flags) 2854534Sbostic register const char *pattern, *string; 2939734Sbostic int flags; 3039734Sbostic { 3139734Sbostic register char c; 3254534Sbostic char test; 3339734Sbostic 3439734Sbostic for (;;) 3539734Sbostic switch (c = *pattern++) { 3639734Sbostic case EOS: 3754534Sbostic return (*string == EOS ? 0 : FNM_NOMATCH); 3839734Sbostic case '?': 3939734Sbostic if ((test = *string++) == EOS || 4039734Sbostic test == '/' && flags & FNM_PATHNAME) 4154534Sbostic return (FNM_NOMATCH); 4239734Sbostic break; 4339734Sbostic case '*': 4439734Sbostic c = *pattern; 4554534Sbostic /* Collapse multiple stars. */ 4639734Sbostic while (c == '*') 4739734Sbostic c = *++pattern; 4839734Sbostic 4954534Sbostic /* Optimize for pattern with * at end or before /. */ 5039734Sbostic if (c == EOS) 5139734Sbostic if (flags & FNM_PATHNAME) 5254534Sbostic return (index(string, '/') == NULL ? 5354534Sbostic 0 : FNM_NOMATCH); 5439734Sbostic else 5554534Sbostic return (0); 5639734Sbostic else if (c == '/' && flags & FNM_PATHNAME) { 5739734Sbostic if ((string = index(string, '/')) == NULL) 5854534Sbostic return (FNM_NOMATCH); 5939734Sbostic break; 6039734Sbostic } 6139734Sbostic 6254534Sbostic /* General case, use recursion. */ 6339734Sbostic while ((test = *string) != EOS) { 6454534Sbostic if (!fnmatch(pattern, string, flags)) 6554534Sbostic return (0); 6639734Sbostic if (test == '/' && flags & FNM_PATHNAME) 6739734Sbostic break; 6839734Sbostic ++string; 6939734Sbostic } 7054534Sbostic return (FNM_NOMATCH); 7139734Sbostic case '[': 7239734Sbostic if ((test = *string++) == EOS || 7339734Sbostic test == '/' && flags & FNM_PATHNAME) 7454534Sbostic return (FNM_NOMATCH); 7539734Sbostic if ((pattern = rangematch(pattern, test)) == NULL) 7654534Sbostic return (FNM_NOMATCH); 7739734Sbostic break; 7839734Sbostic case '\\': 7954534Sbostic if (!(flags & FNM_NOESCAPE)) { 8039734Sbostic if ((c = *pattern++) == EOS) { 8139734Sbostic c = '\\'; 8239734Sbostic --pattern; 8339734Sbostic } 8439734Sbostic if (c != *string++) 8554534Sbostic return (FNM_NOMATCH); 8639734Sbostic break; 8739734Sbostic } 8839734Sbostic /* FALLTHROUGH */ 8939734Sbostic default: 9039734Sbostic if (c != *string++) 9154534Sbostic return (FNM_NOMATCH); 9239734Sbostic break; 9339734Sbostic } 9454534Sbostic /* NOTREACHED */ 9539734Sbostic } 9654534Sbostic 9754535Sbostic static const char * 9854534Sbostic rangematch(pattern, test) 9954535Sbostic register const char *pattern; 10054534Sbostic register int test; 10154534Sbostic { 10254534Sbostic register char c, c2; 10354534Sbostic int negate, ok; 10454534Sbostic 10554534Sbostic if (negate = (*pattern == '!')) 10654534Sbostic ++pattern; 10754534Sbostic 10854534Sbostic /* 10954534Sbostic * XXX 11054534Sbostic * TO DO: quoting 11154534Sbostic */ 11254534Sbostic for (ok = 0; (c = *pattern++) != ']';) { 11354534Sbostic if (c == EOS) 11454534Sbostic return (NULL); /* Illegal pattern. */ 11554534Sbostic if (*pattern == '-' && (c2 = pattern[1]) != EOS && c2 != ']') { 11654534Sbostic if (c <= test && test <= c2) 11754534Sbostic ok = 1; 11854534Sbostic pattern += 2; 11954534Sbostic } 12054534Sbostic else if (c == test) 12154534Sbostic ok = 1; 12254534Sbostic } 12354534Sbostic return (ok == negate ? NULL : pattern); 12454534Sbostic } 125