1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137
|
/*
* Copyright (c) 2000-2001 Proofpoint, Inc. and its suppliers.
* All rights reserved.
*
* By using this file, you agree to the terms and conditions set
* forth in the LICENSE file which can be found at the top level of
* the sendmail distribution.
*
*/
#include <sm/gen.h>
SM_RCSID("@(#)$Id: match.c,v 1.11 2013-11-22 20:51:43 ca Exp $")
#include <sm/string.h>
/*
** SM_MATCH -- Match a character string against a glob pattern.
**
** Parameters:
** str -- string.
** par -- pattern to find in str.
**
** Returns:
** true on match, false on non-match.
**
** A pattern consists of normal characters, which match themselves,
** and meta-sequences. A * matches any sequence of characters.
** A ? matches any single character. A [ introduces a character class.
** A ] marks the end of a character class; if the ] is missing then
** the [ matches itself rather than introducing a character class.
** A character class matches any of the characters between the brackets.
** The range of characters from X to Y inclusive is written X-Y.
** If the first character after the [ is ! then the character class is
** complemented.
**
** To include a ] in a character class, make it the first character
** listed (after the !, if any). To include a -, make it the first
** character listed (after the !, if any) or the last character.
** It is impossible for a ] to be the final character in a range.
** For glob patterns that literally match "*", "?" or "[",
** use [*], [?] or [[].
*/
bool
sm_match(str, pat)
const char *str;
const char *pat;
{
bool ccnot, ccmatch, ccfirst;
const char *ccstart;
char c, c2;
for (;;)
{
switch (*pat)
{
case '\0':
return *str == '\0';
case '?':
if (*str == '\0')
return false;
++pat;
++str;
continue;
case '*':
++pat;
if (*pat == '\0')
{
/* optimize case of trailing '*' */
return true;
}
for (;;)
{
if (sm_match(pat, str))
return true;
if (*str == '\0')
return false;
++str;
}
/* NOTREACHED */
case '[':
ccstart = pat++;
ccnot = false;
if (*pat == '!')
{
ccnot = true;
++pat;
}
ccmatch = false;
ccfirst = true;
for (;;)
{
if (*pat == '\0')
{
pat = ccstart;
goto defl;
}
if (*pat == ']' && !ccfirst)
break;
c = *pat++;
ccfirst = false;
if (*pat == '-' && pat[1] != ']')
{
++pat;
if (*pat == '\0')
{
pat = ccstart;
goto defl;
}
c2 = *pat++;
if (*str >= c && *str <= c2)
ccmatch = true;
}
else
{
if (*str == c)
ccmatch = true;
}
}
if (ccmatch ^ ccnot)
{
++pat;
++str;
}
else
return false;
continue;
default:
defl:
if (*pat != *str)
return false;
++pat;
++str;
continue;
}
}
}
|