home *** CD-ROM | disk | FTP | other *** search
/ The CDPD Public Domain Collection for CDTV 4 / CDPD_IV.bin / networking / tcpip / amitcp-support / wustl-ftpdaemon / support / fnmatch.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-06-29  |  3.7 KB  |  154 lines

  1. /*
  2.  * Copyright (c) 1989 The Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * This code is derived from software contributed to Berkeley by
  6.  * Guido van Rossum.
  7.  *
  8.  * Redistribution and use in source and binary forms are permitted provided
  9.  * that: (1) source distributions retain this entire copyright notice and
  10.  * comment, and (2) distributions including binaries display the following
  11.  * acknowledgement:  ``This product includes software developed by the
  12.  * University of California, Berkeley and its contributors'' in the
  13.  * documentation or other materials provided with the distribution and in
  14.  * all advertising materials mentioning features or use of this software.
  15.  * Neither the name of the University nor the names of its contributors may
  16.  * be used to endorse or promote products derived from this software without
  17.  * specific prior written permission.
  18.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
  19.  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
  20.  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  21.  */
  22.  
  23. #if defined(LIBC_SCCS) && !defined(lint)
  24. static char sccsid[] = "@(#)fnmatch.c    5.3 (Berkeley) 6/23/90";
  25.  
  26. #endif /* LIBC_SCCS and not lint */
  27.  
  28. /*
  29.  * Function fnmatch() as proposed in Posix 1003.2 B.6 (rev. 9).
  30.  * Compares a filename or pathname to a pattern.
  31.  */
  32.  
  33. #include "/src/config.h"
  34.  
  35. #include <string.h>
  36. #include <ctype.h>
  37.  
  38. /* fnmatch function */
  39. #ifndef FNM_PATHNAME
  40. #define    FNM_PATHNAME    0x01    /* match pathnames, not filenames */
  41. #endif
  42.  
  43. #ifndef FNM_QUOTE
  44. #define    FNM_QUOTE    0x02        /* escape special chars with \ */
  45. #endif
  46.  
  47. #ifndef FNM_NOCASE
  48. #define    FNM_NOCASE    0x04        /* case insensitive match */
  49. #endif
  50.  
  51. #define    EOS    '\0'
  52.  
  53. static char *
  54. rangematch(register char *pattern, register char test)
  55. {
  56.     register char c,
  57.       c2;
  58.     int negate,
  59.       ok;
  60.  
  61.     if ( (negate = (*pattern == '!')) )
  62.         ++pattern;
  63.  
  64.     /* TO DO: quoting */
  65.  
  66.     for (ok = 0; (c = *pattern++) != ']';) {
  67.         if (c == EOS)
  68.             return (NULL);        /* illegal pattern */
  69.         if (*pattern == '-' && (c2 = pattern[1]) != EOS && c2 != ']') {
  70.             if (c <= test && test <= c2)
  71.                 ok = 1;
  72.             pattern += 2;
  73.         } else if (c == test)
  74.             ok = 1;
  75.     }
  76.     return (ok == negate ? NULL : pattern);
  77. }
  78.  
  79. int
  80. fnmatch(register char *pattern, register char *string, int flags)
  81. {
  82.     register char c;
  83.     char test;
  84.  
  85. /*
  86.     static char *rangematch();
  87. */
  88.  
  89.     for (;;)
  90.         switch (c = *pattern++) {
  91.         case EOS:
  92.             return (*string == EOS);
  93.         case '?':
  94.             if ( ((test = *string++) == EOS || test == '/') && 
  95.                    (flags & FNM_PATHNAME))
  96.                 return (0);
  97.             break;
  98.         case '*':
  99.             c = *pattern;
  100.             /* collapse multiple stars */
  101.             while (c == '*')
  102.                 c = *++pattern;
  103.  
  104.             /* optimize for pattern with * at end or before / */
  105.             if (c == EOS)
  106.                 if (flags & FNM_PATHNAME)
  107.                     return (!strchr(string, '/'));
  108.                 else
  109.                     return (1);
  110.             else if (c == '/' && flags & FNM_PATHNAME) {
  111.                 if ((string = (char *) strchr(string, '/')) == (char *) NULL)
  112.                     return (0);
  113.                 break;
  114.             }
  115.             /* general case, use recursion */
  116.             while ((test = *string) != EOS) {
  117.                 if (fnmatch(pattern, string, flags))
  118.                     return (1);
  119.                 if (test == '/' && flags & FNM_PATHNAME)
  120.                     break;
  121.                 ++string;
  122.             }
  123.             return (0);
  124.         case '[':
  125.             if ( ((test = *string++) == EOS || test == '/') && 
  126.                   (flags & FNM_PATHNAME) )
  127.                 return (0);
  128.             if ((pattern = rangematch(pattern, test)) == NULL)
  129.                 return (0);
  130.             break;
  131.         case '\\':
  132.             if (flags & FNM_QUOTE) {
  133.                 if ((c = *pattern++) == EOS) {
  134.                     c = '\\';
  135.                     --pattern;
  136.                 }
  137.                 if (c != *string++)
  138.                     return (0);
  139.                 break;
  140.             }
  141.             /* FALLTHROUGH */
  142.         default:
  143.             if (flags & FNM_NOCASE) {
  144.                 if (tolower(c) != tolower(*string))
  145.                     return (0);
  146.             } else {
  147.                 if (c != *string)
  148.                     return (0);
  149.             }
  150.             string++;
  151.             break;
  152.         }
  153. }
  154.